This commit is contained in:
Andrew Beltrano 2021-06-07 17:35:42 -06:00
Родитель a3d4006da5
Коммит dd922ff2a5
115 изменённых файлов: 6033 добавлений и 392 удалений

96
.clang-format Normal file
Просмотреть файл

@ -0,0 +1,96 @@
AccessModifierOffset: -4
AlignAfterOpenBracket: DontAlign
AlignConsecutiveAssignments: false
# AlignConsecutiveBitFields: true
AlignConsecutiveDeclarations: false
# AlignConsecutiveMacros: true
AlignEscapedNewlines: Right
AlignOperands: false
AlignTrailingComments: true
# AllowAllArgumentsOnNextLine: true
# AllowAllConstructorInitializersOnNextLine: false
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: true
AllowShortCaseLabelsOnASingleLine: false
# AllowShortLambdasOnASingleLine: Inline
# AllowShortEnumsOnASingleLine: false
AllowShortFunctionsOnASingleLine: InlineOnly
# AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterReturnType: All
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: Yes
BasedOnStyle: WebKit
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
# AfterCaseLabel: false
AfterClass: true
AfterControlStatement: false
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: false
AfterStruct: true
AfterUnion: true
AfterExternBlock: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: false
SplitEmptyRecord: false
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Custom
BreakInheritanceList: AfterColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: AfterColon
BreakStringLiterals: false
ColumnLimit: 0
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth : 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
# DeriveLineEnding: true
# DerivePointerAlignment: true
FixNamespaceComments: true
IncludeBlocks: Preserve
# IndentCaseBlocks: false
IndentCaseLabels: true
# IndentExternBlock: NoIndent
# IndentGotoLabels: false
IndentPPDirectives: None
IndentWidth: 4
# InsertTrailingCommas: Wrapped
KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
# SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
# SpaceAroundPointerQualifiers: After
SpaceBeforeAssignmentOperators: true
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeRangeBasedForLoopColon: true
# SpaceBeforeSquareBrackets: false
# SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: false
SpacesInContainerLiterals: false
SpacesInCStyleCastParentheses: false
# SpacesInConditionalStatement: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
TabWidth: 4
Standard: Cpp11
# UseCRLF: false
UseTab: Never

372
.gitignore поставляемый
Просмотреть файл

@ -1,350 +1,38 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# Prerequisites
*.d
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
# Compiled Object files
*.slo
*.lo
*.o
*.obj
*.iobj
# Precompiled Headers
*.gch
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Fortran module files
*.mod
*.smod
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Visual Studio Trace Files
*.e2e
# Executables
*.exe
*.out
*.app
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Build directories.
build*/
debug/
release/
.vscode

86
CMakeLists.txt Normal file
Просмотреть файл

@ -0,0 +1,86 @@
# project options
cmake_minimum_required(VERSION 3.14)
project(wifi-telemetry CXX)
# c++ standard options
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
# allow setting target_link_libraries() from any dir
cmake_policy(SET CMP0079 NEW)
# define option for use of Microsoft tracelogging
option(
ENABLE_MS_LTTNG_EXTENSIONS
"Enable use of Microsoft tracelogging extensions for LTTNG"
OFF
)
# define option to build hostap dev dependency in-tree
option(
BUILD_HOSTAP_EXTERNAL
"Build wpa_supplicant/hostapd from built-in external source"
ON
)
# define option to build sdbus-c++ dev dependency in-tree
option(
BUILD_SDBUS_CPP_EXTERNAL
"Build sdbus-c++ from built-in external source"
ON
)
include(ExternalProject)
include(GNUInstallDirs)
include(CheckPIESupported)
include(cmake/find_wpa_client.cmake)
include(cmake/find_systemd.cmake)
include(cmake/FindLTTngUST.cmake)
include(cmake/find_pthreads.cmake)
include(cmake/find_sdbus-cpp.cmake)
if (ENABLE_MS_LTTNG_EXTENSIONS)
include(cmake/find_tracelogging.cmake)
endif()
check_pie_supported()
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
# compilation options
add_compile_options(
-Wall
-Wshadow
-Wformat-security
-Werror
-Wextra
-Wpedantic
-Wconversion
)
if (CMAKE_C_COMPILER_ID STREQUAL "Clang")
add_compile_options(
-fstack-protector
-fvisibility=hidden
)
elseif (CMAKE_C_COMPILER_ID STREQUAL "GNU")
add_compile_options(
-fstack-clash-protection
-fstack-protector-all
-fvisibility=hidden
-Wl,-z,noexecstack
-Wl,-z,now
-Wl,-z,relro
)
endif()
if (CMAKE_BUILD_TYPE MATCHES "(Release|RelWithDebInfo|MinSizeRel)")
add_compile_definitions(_FORTIFY_SOURCE=2)
endif()
if (ENABLE_MS_LTTNG_EXTENSIONS)
add_compile_definitions(TRACE_USE_TRACELOGGING)
endif()
include_directories(include)
add_subdirectory(src)

Просмотреть файл

@ -1,33 +1,55 @@
# Project
> This repo has been populated by an initial template to help get you started. Please
> make sure to update the content to build a great experience for community-building.
As the maintainer of this project, please make a few updates:
- Improving this README.MD file to provide a great experience
- Updating SUPPORT.MD with content about this project's support experience
- Understanding the security reporting process in SECURITY.MD
- Remove this section from the README
## Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
When you submit a pull request, a CLA bot will automatically determine whether you need to provide
a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
## Trademarks
This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
trademarks or logos is subject to and must follow
[Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
Any use of third-party trademarks or logos are subject to those third-party's policies.
# Wi-Fi Telemetry
This project provides a Wi-Fi telemetry library and daemon. It enables realtime
collection and reporting of Wi-Fi related events. It can be used in conjunction
with the the [wifi-ztp](https://github.com/microsoft/wifi-ztp) project to
analyze and collect Wi-Fi zero touch provisioning telemetry as well (-s ztp
command line option).
## Building
### Ubuntu (focal)
```bash
sudo apt install \
build-essential \
cmake \
git \
liblttng-ust-dev \
libpci-dev \
libssl-dev \
libsystemd-dev \
pkg-config
```
Checkout and build:
```bash
git clone git@github.com:microsoft/wifi-telemetry.git
cd wifi-telemetry
mkdir build && cd $_
cmake ..
make -j $(nproc)
```
## Contributing
This project welcomes contributions and suggestions. Most contributions require you to agree to a
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
the rights to use your contribution. For details, visit [https://cla.opensource.microsoft.com](https://cla.opensource.microsoft.com).
When you submit a pull request, a CLA bot will automatically determine whether you need to provide
a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
provided by the bot. You will only need to do this once across all repos using our CLA.
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
## Trademarks
This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
trademarks or logos is subject to and must follow
[Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
Any use of third-party trademarks or logos are subject to those third-party's policies.

Просмотреть файл

@ -1,25 +1,14 @@
# TODO: The maintainer of this repo has not yet edited this file
**REPO OWNER**: Do you want Customer Service & Support (CSS) support for this product/project?
- **No CSS support:** Fill out this template with information about how to file issues and get help.
- **Yes CSS support:** Fill out an intake form at [aka.ms/spot](https://aka.ms/spot). CSS will work with/help you to determine next steps. More details also available at [aka.ms/onboardsupport](https://aka.ms/onboardsupport).
- **Not sure?** Fill out a SPOT intake as though the answer were "Yes". CSS will help you decide.
*Then remove this first heading from this SUPPORT.MD file before publishing your repo.*
# Support
## How to file issues and get help
This project uses GitHub Issues to track bugs and feature requests. Please search the existing
issues before filing new issues to avoid duplicates. For new issues, file your bug or
feature request as a new Issue.
This project uses GitHub Issues to track bugs and feature requests. Please
search the existing issues before filing new issues to avoid duplicates. For
new issues, file your bug or feature request as a new Issue.
For help and questions about using this project, please **REPO MAINTAINER: INSERT INSTRUCTIONS HERE
FOR HOW TO ENGAGE REPO OWNERS OR COMMUNITY FOR HELP. COULD BE A STACK OVERFLOW TAG OR OTHER
CHANNEL. WHERE WILL YOU HELP PEOPLE?**.
For help and questions about using this project, please contact
<wifiztpsupport@microsoft.com>.
## Microsoft Support Policy
Support for this **PROJECT or PRODUCT** is limited to the resources listed above.
Support for this project is limited to the resources listed above.

116
cmake/FindLTTngUST.cmake Normal file
Просмотреть файл

@ -0,0 +1,116 @@
#.rst:
# FindLTTngUST
# ------------
#
# This module finds the `LTTng-UST <http://lttng.org/>`__ library.
#
# Imported target
# ^^^^^^^^^^^^^^^
#
# This module defines the following :prop_tgt:`IMPORTED` target:
#
# ``LTTng::UST``
# The LTTng-UST library, if found
#
# Result variables
# ^^^^^^^^^^^^^^^^
#
# This module sets the following
#
# ``LTTNGUST_FOUND``
# ``TRUE`` if system has LTTng-UST
# ``LTTNGUST_INCLUDE_DIRS``
# The LTTng-UST include directories
# ``LTTNGUST_LIBRARIES``
# The libraries needed to use LTTng-UST
# ``LTTNGUST_VERSION_STRING``
# The LTTng-UST version
# ``LTTNGUST_HAS_TRACEF``
# ``TRUE`` if the ``tracef()`` API is available in the system's LTTng-UST
# ``LTTNGUST_HAS_TRACELOG``
# ``TRUE`` if the ``tracelog()`` API is available in the system's LTTng-UST
#=============================================================================
# Copyright 2016 Kitware, Inc.
# Copyright 2016 Philippe Proulx <pproulx@efficios.com>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
find_path(LTTNGUST_INCLUDE_DIRS NAMES lttng/tracepoint.h)
# Must also check for the path of generated header files since out-of-tree
# build is a possibility (Yocto).
find_path(LTTNGUST_INCLUDE_DIRS_GENERATED NAMES lttng/ust-config.h)
find_library(LTTNGUST_LIBRARIES NAMES lttng-ust)
if(LTTNGUST_INCLUDE_DIRS AND LTTNGUST_INCLUDE_DIRS_GENERATED AND LTTNGUST_LIBRARIES)
# find tracef() and tracelog() support
set(LTTNGUST_HAS_TRACEF 0)
set(LTTNGUST_HAS_TRACELOG 0)
if(EXISTS "${LTTNGUST_INCLUDE_DIRS}/lttng/tracef.h")
set(LTTNGUST_HAS_TRACEF TRUE)
endif()
if(EXISTS "${LTTNGUST_INCLUDE_DIRS}/lttng/tracelog.h")
set(LTTNGUST_HAS_TRACELOG TRUE)
endif()
# get version
set(lttngust_version_file "${LTTNGUST_INCLUDE_DIRS_GENERATED}/lttng/ust-version.h")
if(EXISTS "${lttngust_version_file}")
file(STRINGS "${lttngust_version_file}" lttngust_version_major_string
REGEX "^[\t ]*#define[\t ]+LTTNG_UST_MAJOR_VERSION[\t ]+[0-9]+[\t ]*$")
file(STRINGS "${lttngust_version_file}" lttngust_version_minor_string
REGEX "^[\t ]*#define[\t ]+LTTNG_UST_MINOR_VERSION[\t ]+[0-9]+[\t ]*$")
file(STRINGS "${lttngust_version_file}" lttngust_version_patch_string
REGEX "^[\t ]*#define[\t ]+LTTNG_UST_PATCHLEVEL_VERSION[\t ]+[0-9]+[\t ]*$")
string(REGEX REPLACE ".*([0-9]+).*" "\\1"
lttngust_v_major "${lttngust_version_major_string}")
string(REGEX REPLACE ".*([0-9]+).*" "\\1"
lttngust_v_minor "${lttngust_version_minor_string}")
string(REGEX REPLACE ".*([0-9]+).*" "\\1"
lttngust_v_patch "${lttngust_version_patch_string}")
set(LTTNGUST_VERSION_STRING
"${lttngust_v_major}.${lttngust_v_minor}.${lttngust_v_patch}")
unset(lttngust_version_major_string)
unset(lttngust_version_minor_string)
unset(lttngust_version_patch_string)
unset(lttngust_v_major)
unset(lttngust_v_minor)
unset(lttngust_v_patch)
else()
message(FATAL_ERROR "Missing version header")
endif()
unset(lttngust_version_file)
if(NOT TARGET LTTng::UST)
add_library(LTTng::UST UNKNOWN IMPORTED)
set_target_properties(LTTng::UST PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${LTTNGUST_INCLUDE_DIRS};${LTTNGUST_INCLUDE_DIRS_GENERATED}"
INTERFACE_LINK_LIBRARIES ${CMAKE_DL_LIBS}
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
IMPORTED_LOCATION "${LTTNGUST_LIBRARIES}")
endif()
# add libdl to required libraries
set(LTTNGUST_LIBRARIES ${LTTNGUST_LIBRARIES} ${CMAKE_DL_LIBS})
endif()
# handle the QUIETLY and REQUIRED arguments and set LTTNGUST_FOUND to
# TRUE if all listed variables are TRUE
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(LTTngUST FOUND_VAR LTTNGUST_FOUND
REQUIRED_VARS LTTNGUST_LIBRARIES
LTTNGUST_INCLUDE_DIRS
VERSION_VAR LTTNGUST_VERSION_STRING)
mark_as_advanced(LTTNGUST_LIBRARIES LTTNGUST_INCLUDE_DIRS)

Просмотреть файл

@ -0,0 +1,2 @@
find_package(Threads REQUIRED)

Просмотреть файл

@ -0,0 +1,6 @@
if (BUILD_SDBUS_CPP_EXTERNAL)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../external/sdbus-c++)
else()
find_package(sdbus-c++ REQUIRED)
endif()

9
cmake/find_systemd.cmake Normal file
Просмотреть файл

@ -0,0 +1,9 @@
find_library(LIBSYSTEMD
NAMES libsystemd.so
REQUIRED)
if(LIBSYSTEMD)
set(LIBSYSTEMD_TARGET ${LIBSYSTEMD})
endif()
MESSAGE(STATUS LIBSYSTEMD=${LIBSYSTEMD})

Просмотреть файл

@ -0,0 +1,2 @@
find_package(tracelogging REQUIRED)

Просмотреть файл

@ -0,0 +1,12 @@
if (BUILD_HOSTAP_EXTERNAL)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../external/hostap)
else()
find_library(LIBWPA_CLIENT
NAMES libwpa_client.so
REQUIRED)
endif()
if(LIBWPA_CLIENT)
set(LIBWPA_CLIENT_TARGET ${LIBWPA_CLIENT})
MESSAGE(STATUS "Found wpa client: ${LIBWPA_CLIENT}")
endif()

Просмотреть файл

@ -0,0 +1,9 @@
include(CMakeFindDependencyMacro)
find_library(LIBSYSTEMD NAMES libsystemd.so)
find_library(LIBWPA_CLIENT NAMES libwpa_client.so)
find_dependency(LTTngUST)
find_dependency(Threads)
include("${CMAKE_CURRENT_LIST_DIR}/wifi-telemetry-targets.cmake")

2
external/hostap/.config поставляемый Normal file
Просмотреть файл

@ -0,0 +1,2 @@
CONFIG_CTRL_IFACE=y
CONFIG_BUILD_WPA_CLIENT_SO=y

23
external/hostap/CMakeLists.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,23 @@
find_program(MAKE_EXE
NAMES gmake nmake make
REQUIRED
)
set(HOSTAP_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/hostap-prefix/src/hostap/wpa_supplicant)
ExternalProject_Add(hostap
GIT_REPOSITORY "http://w1.fi/hostap.git"
GIT_TAG "5f082c158c49a23614b69e4465e9a7299f004f5f"
CONFIGURE_COMMAND cp -n ${CMAKE_CURRENT_SOURCE_DIR}/.config ${HOSTAP_PREFIX}/.config
BINARY_DIR ${HOSTAP_PREFIX}
BUILD_COMMAND QUIET=1 $(MAKE) libwpa_client.so
INSTALL_DIR ${HOSTAP_PREFIX}
INSTALL_COMMAND QUIET=1 $(MAKE) install
)
set(LIBWPA_CLIENT
${HOSTAP_PREFIX}/libwpa_client.so
CACHE FILEPATH
"wpa client shared object"
)

23
external/sdbus-c++/CMakeLists.txt поставляемый Normal file
Просмотреть файл

@ -0,0 +1,23 @@
set(SDBUS_CPP_PREFIX ${CMAKE_CURRENT_BINARY_DIR}/sdbus-cpp-prefix)
ExternalProject_Add(sdbus-cpp
GIT_REPOSITORY "https://github.com/Kistler-Group/sdbus-cpp.git"
GIT_TAG "v0.8.3"
)
set(SDBUS_CPP_EXTERNAL_LIBS
"${SDBUS_CPP_PREFIX}/src/sdbus-cpp-build"
CACHE PATH
"Directory of external sdbus-c++ libraries"
)
set(SDBUS_CPP_EXTERNAL_NAME
sdbus-c++
CACHE STRING
"sdbus-c++ shared object name"
)
set(SDBUS_CPP_EXTERNAL
${SDBUS_CPP_EXTERNAL_LIBS}/lib${SDBUS_CPP_EXTERNAL_NAME}.so
CACHE FILEPATH
"sdbus-c++ shared object"
)

Просмотреть файл

@ -0,0 +1,230 @@
#ifndef __WIFI_80211_HPP__
#define __WIFI_80211_HPP__
#include <array>
#include <cstdint>
/**
* @brief Unsolicited Management Frame reason code for Disassociation.
* @see IEEE Std 802.11-2016, Section 9.4.1.7, Table 9-45.
*/
enum class WifiDeauthenticationReasonCode : uint16_t
{
Unspecified = 1,
InvalidAuthentication = 2,
LeavingNetworkDeauth = 3,
Inactivity = 4,
NoMoreStas = 5,
InvalidClass2Frame = 6,
InvalidClass3Frame = 7,
LeavingNetworkDisassoc = 8,
NotAuthenticated = 9,
UnacceptablePowerCapability = 10,
UnacceptableSupportedChannels = 11,
BssTransitionDeassocac = 12,
InvalidElement = 13,
MicFailure = 14,
FourWayHandshakeTimeout = 15,
GroupKeyHandshakeTimeout = 16,
HandshakeElementMismatch = 17,
InvalidGroupCipher = 18,
InvalidPairwiseCipher = 19,
InvalidAkmp = 20,
UnsupportedRsneVersion = 21,
InvalidRsneCapabilities = 22,
Ieee80211XAuthFailed = 23,
CipherOutOfPolicy = 24,
TdlsPeerUnreachable = 25,
TdlsUnspecifiedReason = 26,
SspRequestedDissassoc = 27,
NoSspRoamingAgreement = 28,
BadCipherOrAkm = 29,
NotAuthorizedThisLocation = 30,
ServiceChangePrecludesTs = 31,
UnspecifiedQosReason = 32,
NotEnoughBandwidth = 33,
MissingAcks = 34,
ExceededTxop = 35,
StaLeaving = 36,
EndTsBaDls = 37,
UnknownTsBa = 38,
Timeout = 39,
PeerkeyMismatch = 45,
PeerInitiated = 46,
ApInitiated = 47,
InvalidFtActionFrameCount = 48,
InvalidPmkid = 49,
InvalidMde = 50,
InvalidFte = 51,
MeshPeeringCanceled = 52,
MeshMaxPeers = 53,
MeshConfigurationPolicyViolation = 54,
MeshCloseRecvd = 55,
MeshMaxRetries = 56,
MeshConfirmTimeout = 57,
MeshInvalidGtk = 58,
MeshInconsistentParameters = 59,
MeshInvalidSecurityCapability = 60,
MeshPathErrorNoProxyInformation = 61,
MeshPathErrorNoForwardingInformation = 62,
MeshPathErrorDestinationUnreachable = 63,
MaxAddressAlreadyExistsInMbss = 64,
MeshChannelSwitchRegulatoryRequirements = 65,
MeshChannelSwitchUnspecified = 66,
};
/**
* @brief Unsolicited Management Frame status code.
* @see IEEE Std 802.11-2016, Section 9.4.1.9, Table 9-46.
*/
enum class WifiStatusCode : uint16_t
{
Success = 0,
Refused = 1,
TdlsRejectedAlternativeProvided = 2,
TdlsRejected = 3,
/* reserved = 4 */
SecurityDisabled = 5,
UnacceptableLifetime = 6,
NotInSameBss = 7,
/* reserved = 8-9 */
RefusedCapabilitiesMismatch = 10,
DeniedNoAssociationExists = 11,
DeniedOtherReason = 12,
UnsupportedAuthAlgorithm = 13,
TransactionSequenceError = 14,
ChallengeFailure = 15,
RejectedSequenceTimeout = 16,
DeniedNoMoreStas = 17,
RefusedBasicRatesMismatch = 18,
DeniedNoShortPreableSupport = 19,
/* reserved = 20-21 */
RejectedSpectrumManagementRequired = 22,
RejectedBadPowerCapability = 23,
RejectedBadSupportedChannels = 24,
DeniedNoShortSlotTimeSupport = 25,
/* reserved = 26 */
DeniedNoHtSupport = 27,
R0KHUnreachable = 28,
DeniedPcoTimeNotSupported = 29,
RefusedTemporarily = 30,
RobustManagementPolicyViolation = 31,
UnspecifiedQosFailure = 32,
DeniedInsufficientBandwidth = 33,
DeniedPoorChannelConditions = 34,
DeniedQosNotSupported = 35,
/* reserved = 36 */
RequestDeclined = 37,
InvalidParameters = 38,
RejectedWithSuggestedChanges = 39,
StatusInvalidElement = 40,
StatusInvalidGroupCipher = 41,
StatusInvalidPairwiseCipher = 42,
StatusInvalidAkmp = 43,
UnsupportedRsneVersion = 44,
InvalidRsneCapabilities = 45,
StatusCipherOutOfPolicy = 46,
RejectedForDelayPeriod = 47,
DlsNotAllowed = 48,
NotPresent = 49,
NotQosSta = 50,
DeniedListenIntervalTooLarge = 51,
StatusInvalidFtActionFrameCount = 52,
StatusInvalidPmkid = 53,
StatusInvalidMde = 54,
StatusInvalidFte = 55,
RequestTclasNotSupported = 56,
InsufficientTclasProcessingResources = 57,
TryAnotherBss = 58,
GasAdvertisementProtocolNotSupported = 59,
NoOutstandingGasRequest = 60,
GasResponseNotReceivedFromServer = 61,
GasQueryTimeout = 62,
GasQueryResponseTooLarge = 63,
RejectedHomeWithSuggestedChanges = 64,
ServerUnreachable = 65,
/* reserved = 66 */
RejectedForSspPermissions = 67,
RefusedUnauthenticatedAccessNotSupported = 68,
/* reserved = 69-71 */
InvalidRsne = 72,
UApsdCoexistanceNotSupported = 73,
UApsdCoexModeNotSupported = 74,
BadIntervalWithUApsdCoex = 75,
AntiCloggingTokenRequired = 76,
UnsupportedFiniteCyclicGroup = 77,
CannotFindAlternativeTbtt = 78,
TransmissionFailure = 79,
RequestTclassNotSupported = 80,
TclasResourcesExhausted = 81,
RejectedWithSuggestedBssTransition = 82,
RejectWithSchedule = 83,
RejectNoWakeupSpecified = 84,
SuccessPowerSaveMode = 85,
PendingAdmittingFstSession = 86,
PerformingFstNow = 87,
PendingGapInBaWindow = 88,
RejectUPidSetting = 89,
/* reserved = 90-91 */
RefusedExternalReason = 92,
RefusedApOutOutMemory = 93,
RejectedEmergencyServicesNotSupported = 94,
QueryResponseOutstanding = 95,
RejectBadDseBand = 96,
TclasProcessingTerminated = 97,
TsScheduleConflict = 98,
DeniedWithSuggestedBandAndChannel = 99,
MccaopReservationConflict = 100,
MafLimitExceeded = 101,
MccaTrackLimitExceeded = 102,
DeniedDueToSpectrumManagement = 103,
DeniedVhtNotSupported = 104,
EnablementDenied = 105,
RestrictionFromAuthorixzedGdb = 106,
AuthorizationDeenabled = 107,
/* reserved = 108-165, 535 */
};
enum class WifiAuthenticationType : uint32_t
{
Unknown = 0x0000,
Open = 0x0001,
WpaPsk = 0x0002,
Shared = 0x0004,
Wpa = 0x0008,
Wpa2 = 0x0010,
Wpa2Psk = 0x0020,
};
inline const char*
WifiAuthenticationTypeToString(const WifiAuthenticationType auth_type)
{
static const char* strs[] = {
"unknown",
"open",
"wpa-psk",
"shared",
"wpa",
"wpa2",
"wpa2-psk"
};
return strs[unsigned(auth_type)];
}
typedef std::array<uint8_t, 6> wifi_80211_mac;
#define WIFI_80211_MAC_FMT "%2hhx:%2hhx:%2hhx:%2hhx:%2hhx:%2hhx"
#define STR_2_WIFI80211_MAC(a) &a[0], &a[1], &a[2], &a[3], &a[4], &a[5]
static const wifi_80211_mac wifi_80211_any_address{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const wifi_80211_mac wifi_80211_broadcast_address{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
static inline bool
is_wifi80211_broadcast_address(const wifi_80211_mac& mac)
{
return mac == wifi_80211_broadcast_address;
}
#endif //__WIFI_80211_HPP__

Просмотреть файл

@ -0,0 +1,123 @@
#ifndef __WIFI_FORMAT_80211_MAC_HPP__
#define __WIFI_FORMAT_80211_MAC_HPP__
#include <iomanip>
#include <sstream>
#include <string>
#include <type_traits>
#include "wifi-telemetry/wifi/wifi_80211.hpp"
class put_dot11mac
{
public:
put_dot11mac(
const wifi_80211_mac& mac,
const char separator = ':') :
m_mac(mac),
m_separator(separator)
{}
std::ostream&
operator()(
std::ostream& out)
{
out << std::setbase(16)
<< std::setw(2) << std::setfill('0') << short(m_mac[0]) << m_separator
<< std::setw(2) << std::setfill('0') << short(m_mac[1]) << m_separator
<< std::setw(2) << std::setfill('0') << short(m_mac[2]) << m_separator
<< std::setw(2) << std::setfill('0') << short(m_mac[3]) << m_separator
<< std::setw(2) << std::setfill('0') << short(m_mac[4]) << m_separator
<< std::setw(2) << std::setfill('0') << short(m_mac[5])
<< std::setbase(0);
return out;
}
private:
const wifi_80211_mac& m_mac;
const char m_separator;
};
inline std::ostream&
operator<<(
std::ostream& out,
put_dot11mac manipulator)
{
return manipulator(out);
}
class get_dot11mac
{
public:
get_dot11mac(
wifi_80211_mac& mac,
const char separator = ':') :
m_mac(mac),
m_separator(separator)
{}
std::istream&
operator()(
std::istream& in)
{
static constexpr std::size_t c_NumOctets = std::tuple_size<std::decay<decltype(m_mac)>::type>::value;
static constexpr std::size_t c_NumSeparators = c_NumOctets - 1;
uint32_t mac[c_NumOctets];
char separators[c_NumSeparators];
in >> std::setbase(16)
>> mac[0] >> separators[0]
>> mac[1] >> separators[1]
>> mac[2] >> separators[2]
>> mac[3] >> separators[3]
>> mac[4] >> separators[4]
>> mac[5]
>> std::setbase(0);
for (std::size_t i = 0; i < c_NumOctets; i++) {
if (i < c_NumSeparators && separators[i] != m_separator) {
in.setstate(std::ios_base::failbit);
break;
}
m_mac[i] = uint8_t(mac[i] & 0x000000FF);
}
return in;
}
private:
wifi_80211_mac& m_mac;
const char m_separator;
};
inline std::istream&
operator>>(
std::istream& in,
get_dot11mac manipulator)
{
return manipulator(in);
}
inline std::string
wifi_80211_mac_to_string(const wifi_80211_mac& mac, const char separator = ':')
{
std::ostringstream ss;
ss << put_dot11mac(mac, separator);
return ss.str();
}
inline wifi_80211_mac
wifi_80211_mac_from_string(const std::string& mac_str, const char separator = ':')
{
std::istringstream ss(mac_str);
wifi_80211_mac mac;
ss >> get_dot11mac(mac, separator);
return mac;
}
#endif //__WIFI_FORMAT_80211_MAC_HPP__

Просмотреть файл

@ -0,0 +1,11 @@
#ifndef __WIFI_COMMON_HPP__
#define __WIFI_COMMON_HPP__
enum class WifiOperationalMode
{
Station,
AccessPoint,
};
#endif //__WIFI_COMMON_HPP__

Просмотреть файл

@ -0,0 +1,102 @@
#ifndef __WIFI_DPP_HPP__
#define __WIFI_DPP_HPP__
enum class WifiDppRole
{
Initiator,
Responder
};
inline const char*
WifiDppRoleToString(const WifiDppRole role)
{
static const char* strs[] = {
"initiator",
"responder"
};
return strs[unsigned(role)];
}
enum class WifiDppDeviceRole
{
Enrollee,
Configurator
};
inline const char*
WifiDppDeviceRoleToString(const WifiDppDeviceRole role)
{
static const char* strs[] = {
"enrollee",
"configurator"
};
return strs[unsigned(role)];
}
enum class WifiDppExchangeEnrolleeState
{
Bootstrapping,
Authenticated,
Provisioning,
Provisioned,
Terminated
};
inline const char*
WifiDppExchangeEnrolleeStateToString(const WifiDppExchangeEnrolleeState state)
{
static const char* strs[] = {
"bootstrapping",
"authenticated",
"provisioning",
"provisioned",
"terminated"
};
return strs[unsigned(state)];
}
enum class WifiDppExchangeConfiguratorState
{
Bootstrapping,
Authenticated,
Finished,
Terminated
};
inline const char*
WifiDppExchangeConfiguratorStateToString(const WifiDppExchangeConfiguratorState state)
{
static const char* strs[] = {
"bootstrapping",
"authenticated",
"finished",
"terminated"
};
return strs[unsigned(state)];
}
enum class WifiDppFailureType
{
None,
Unspecified,
AuthenticationTimeout,
};
inline const char*
WifiDppFailureTypeToString(const WifiDppFailureType type)
{
static const char* strs[] = {
"none",
"unspecified",
"authentication-timeout",
};
return strs[unsigned(type)];
}
#endif //__WIFI_DPP_HPP__

Просмотреть файл

@ -0,0 +1,80 @@
#ifndef __WIFI_DPP_EXCHANGE_HPP__
#define __WIFI_DPP_EXCHANGE_HPP__
#include <chrono>
#include <optional>
#include <string>
#include <unordered_set>
#include "wifi-telemetry/wifi/wifi_80211.hpp"
#include "wifi-telemetry/wifi/wifi_common.hpp"
#include "wifi-telemetry/wifi/wifi_dpp.hpp"
struct WifiDppExchange
{
WifiDppExchange(WifiDppDeviceRole device_role_, WifiDppRole role_) :
WifiDppExchange(device_role_, role_, std::chrono::system_clock::now())
{}
WifiDppExchange(WifiDppDeviceRole device_role_, WifiDppRole role_, std::chrono::time_point<std::chrono::system_clock> timestamp_start_) :
device_role(device_role_),
role(role_),
timestamp_start(timestamp_start_)
{}
virtual ~WifiDppExchange(void) = default;
void
start(void)
{
if (!timestamp_start)
timestamp_start = std::chrono::system_clock::now();
}
void
stop(void)
{
if (timestamp_start && !timestamp_end) {
timestamp_end = std::chrono::system_clock::now();
duration = std::chrono::duration_cast<std::chrono::milliseconds>(timestamp_end.value() - timestamp_start.value());
}
}
WifiDppDeviceRole device_role;
WifiDppRole role;
WifiDppFailureType failure_type = WifiDppFailureType::None;
std::optional<std::string> failure_details;
std::optional<std::chrono::time_point<std::chrono::system_clock>> timestamp_start;
std::optional<std::chrono::time_point<std::chrono::system_clock>> timestamp_end;
std::optional<std::chrono::milliseconds> duration;
};
struct WifiDppExchangeEnrollee :
public WifiDppExchange
{
WifiDppExchangeEnrollee(WifiDppRole role_) :
WifiDppExchange(WifiDppDeviceRole::Enrollee, role_)
{}
WifiDppExchangeEnrolleeState state = WifiDppExchangeEnrolleeState::Bootstrapping;
std::unordered_set<uint32_t> chirp_frequencies;
};
struct WifiDppExchangeConfigurator :
public WifiDppExchange
{
WifiDppExchangeConfigurator(int32_t peer_id_, const wifi_80211_mac peer_bssid_, uint32_t frequency_, WifiDppRole role_) :
WifiDppExchange(WifiDppDeviceRole::Configurator, role_),
peer_id(peer_id_),
peer_bssid(peer_bssid_),
frequency(frequency_)
{}
WifiDppExchangeConfiguratorState state = WifiDppExchangeConfiguratorState::Bootstrapping;
int32_t peer_id;
wifi_80211_mac peer_bssid;
uint32_t frequency;
};
#endif //__WIFI_DPP_EXCHANGE_HPP__

Просмотреть файл

@ -0,0 +1,14 @@
#ifndef __WIFI_TELEMETRY_80211_HPP__
#define __WIFI_TELEMETRY_80211_HPP__
enum class WifiConnectionAttemptResult
{
Succeeded = 0,
Unspecified = 1,
AuthenticationRejected = 2,
AssociationRejected = 3,
NetworkNotFound = 4,
};
#endif // __WIFI_TELEMETRY_80211_HPP__

Просмотреть файл

@ -0,0 +1,24 @@
#ifndef __WIFI_INTERFACE_CONFIGURATION_HPP__
#define __WIFI_INTERFACE_CONFIGURATION_HPP__
#include <string>
#include "wifi-telemetry/wifi/wifi_common.hpp"
struct WifiInterfaceConfiguration
{
WifiInterfaceConfiguration(const std::string& name_, const WifiOperationalMode operational_mode_) :
name(name_),
operational_mode(operational_mode_)
{}
WifiInterfaceConfiguration(const std::string& name_) :
WifiInterfaceConfiguration(name_, WifiOperationalMode::Station)
{}
std::string name;
WifiOperationalMode operational_mode;
};
#endif //__WIFI_INTERFACE_CONFIGURATION_HPP__

Просмотреть файл

@ -0,0 +1,103 @@
#ifndef __WIFI_TELEMETRY_MONITOR_HPP__
#define __WIFI_TELEMETRY_MONITOR_HPP__
#include <memory>
#include <type_traits>
#include <vector>
#include "wifi-telemetry/wifi_interface_configuration.hpp"
#include "wifi-telemetry/wifi_telemetry_source_instance.hpp"
#include "wifi-telemetry/wifi_telemetry_source.hpp"
#include "wifi-telemetry/wifi/wifi_common.hpp"
class __attribute__ ((visibility ("default"))) WifiTelemetryMonitor
{
public:
/**
* @brief Construct a new Wifi Telemetry Monitor object.
*/
WifiTelemetryMonitor(void);
~WifiTelemetryMonitor(void);
/**
* @brief Adds a new telemetry source.
*
* @tparam TSource The type of the telemetry source. Must be a type deriving from WifiTelemetrySource.
* @tparam TSourceArgs The parameter pack type for T's constructor arguments.
* @param interface The interface configuration of the source (if any).
* @param activation_args The arguments needed to activate the telemetry source, or nullptr if none.
* @param args The arguments to forward to the constructor of type TSource.
* @return std::shared_ptr<TSource>
*/
template <
typename TSource,
typename ...TSourceArgs,
typename std::enable_if<std::is_base_of<WifiTelemetrySource, TSource>::value>* = nullptr
>
std::shared_ptr<TSource>
add_source(const std::optional<WifiInterfaceConfiguration>& interface, const std::shared_ptr<WifiTelemetrySourceActivationArgs> activation_args, TSourceArgs... args)
{
std::shared_ptr<TSource> source = std::make_shared<TSource>(interface, args...);
add_source_impl(source, activation_args);
return source;
}
/**
* @brief Adds a new telemetry source. This version assumes no activation args are required.
*
* @tparam TSource The type of the telemetry source. Must be a type deriving from WifiTelemetrySource.
* @tparam TSourceArgs The parameter pack type for T's constructor arguments.
* @param interface The interface configuration of the source (if any).
* @param args The arguments to forward to the constructor of type TSource.
* @return std::shared_ptr<TSource>
*/
template <
typename TSource,
typename ...TSourceArgs,
typename std::enable_if<std::is_base_of<WifiTelemetrySource, TSource>::value>* = nullptr
>
std::shared_ptr<TSource>
add_source(const std::optional<WifiInterfaceConfiguration>& interface, TSourceArgs&&... args)
{
std::shared_ptr<TSource> source = std::make_shared<TSource>(interface, args...);
add_source_impl(source);
return source;
}
/**
* @brief Removes a telemetry source from the monitor.
*
* @param source A previously added telemetry source.
*/
void
remove_source(const std::shared_ptr<WifiTelemetrySource> source);
/**
* @brief Starts monitoring the configured interface.
*/
void
start(void);
/**
* @brief Stops monitoring the configured interface.
*/
void
stop(void);
private:
void
add_source_impl(const std::shared_ptr<WifiTelemetrySource> source, const std::shared_ptr<WifiTelemetrySourceActivationArgs> activation_args = nullptr);
std::size_t
activate_sources(void);
void
deactivate_sources(void);
protected:
bool m_activated = false;
std::vector<std::unique_ptr<WifiTelemetrySourceInstance>> m_sources;
};
#endif //__WIFI_TELEMETRY_MONITOR_HPP__

Просмотреть файл

@ -0,0 +1,44 @@
#ifndef __WIFI_TELEMETRY_SOURCE_HPP__
#define __WIFI_TELEMETRY_SOURCE_HPP__
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include "wifi-telemetry/wifi/wifi_common.hpp"
#include "wifi-telemetry/wifi_interface_configuration.hpp"
struct WifiTelemetrySourceActivationArgs
{
~WifiTelemetrySourceActivationArgs(void) = default;
};
class WifiTelemetrySource
{
protected:
WifiTelemetrySource(const std::optional<WifiInterfaceConfiguration>& interface);
WifiTelemetrySource(const std::optional<WifiInterfaceConfiguration>& interface, const std::string& name);
public:
virtual ~WifiTelemetrySource(void);
virtual int
activate(const std::shared_ptr<WifiTelemetrySourceActivationArgs> args);
virtual void
deactivate(void);
virtual const std::string_view
name() const;
const std::optional<WifiInterfaceConfiguration>&
interface(void) const;
protected:
std::string m_name = "unnamed";
const std::optional<WifiInterfaceConfiguration> m_interface;
};
#endif //__WIFI_TELEMETRY_SOURCE_HPP__

Просмотреть файл

@ -0,0 +1,23 @@
#ifndef __WIFI_TELEMETRY_SOURCE_INSTANCE_HPP__
#define __WIFI_TELEMETRY_SOURCE_INSTANCE_HPP__
#include <memory>
#include "wifi-telemetry/wifi_telemetry_source.hpp"
struct WifiTelemetrySourceInstance
{
public:
WifiTelemetrySourceInstance(std::shared_ptr<WifiTelemetrySource> source_, const std::shared_ptr<WifiTelemetrySourceActivationArgs> args_) :
source(std::move(source_)),
args(args_)
{}
virtual ~WifiTelemetrySourceInstance(void) = default;
std::shared_ptr<WifiTelemetrySource> source;
std::shared_ptr<WifiTelemetrySourceActivationArgs> args;
};
#endif // __WIFI_TELEMETRY_SOURCE_INSTANCE_HPP__

Просмотреть файл

@ -0,0 +1,110 @@
#ifndef __WIFI_TELEMETRY_SOURCE_WPA_HPP__
#define __WIFI_TELEMETRY_SOURCE_WPA_HPP__
#include <memory>
#include <optional>
#include <string>
#include "wifi-telemetry/wifi/wifi_common.hpp"
#include "wifi-telemetry/wifi/wifi_dpp_exchange.hpp"
#include "wifi-telemetry/wifi_telemetry_source.hpp"
#include "wifi-telemetry/wpa/wifi_telemetry_input_station_connection_attempt.hpp"
#include "wifi-telemetry/wpa/wpa_controller.hpp"
class __attribute__((visibility("default"))) WifiTelemetrySourceWpa :
public WifiTelemetrySource,
public std::enable_shared_from_this<WifiTelemetrySourceWpa>,
public WpaEventHandler
{
public:
WifiTelemetrySourceWpa(const std::optional<WifiInterfaceConfiguration>& interface);
~WifiTelemetrySourceWpa(void);
int
activate(const std::shared_ptr<WifiTelemetrySourceActivationArgs> args) override;
void
deactivate(void) override;
private:
bool
trace_station(void) const;
bool
trace_ap(void) const;
bool
trace_dpp(void) const;
bool
trace_dpp_enrollee(void) const;
bool
trace_dpp_configurator(void) const;
// WpaEventHandler
void
on_connected(const WpaEventArgs<WpaEventConnected>& args) override;
void
on_disconnected(const WpaEventArgs<WpaEventDisconnected>& args) override;
void
on_association_rejected(const WpaEventArgs<WpaEventAssociationRejected>& args) override;
void
on_authentication_rejected(const WpaEventArgs<WpaEventAuthenticationRejected>& args) override;
void
on_network_not_found(const WpaEventArgs<WpaEventNetworkNotFound>& args) override;
void
on_dpp_chirp_received(const WpaEventArgs<WpaEventDppChirpReceived>& args) override;
void
on_dpp_frame_transmit_status(const WpaEventArgs<WpaEventDppFrameTransmitStatus>& args) override;
void
on_dpp_authentication_init_failure(const WpaEventArgs<WpaEventDppAuthenticationInitFailure>& args) override;
void
on_dpp_authentication_succeeded(const WpaEventArgs<WpaEventDppAuthenticationSucceeded>& args) override;
void
on_dpp_configuration_received(const WpaEventArgs<WpaEventDppConfigurationReceived>& args) override;
void
on_dpp_configuration_sent(const WpaEventArgs<WpaEventDppConfigurationSent>& args) override;
void
on_dpp_failure(const WpaEventArgs<WpaEventDppFailure>& args) override;
private:
template<
typename T,
typename std::enable_if<std::is_base_of<WifiDppExchange, T>::value>* = nullptr>
std::shared_ptr<T>
resolve_dpp_exchange(void)
{
return std::dynamic_pointer_cast<T>(m_dpp_exchange);
}
bool
is_dpp_exchange_in_progress(void) const;
void
complete_connection_attempt(const WifiTelemetryInputStationConnectionAttempt& input);
void
complete_dpp_exchange_enrollee(std::shared_ptr<WifiDppExchangeEnrollee>& enrollee);
void
complete_dpp_exchange_configurator(std::shared_ptr<WifiDppExchangeConfigurator>& configurator);
std::shared_ptr<WifiDppExchange> m_dpp_exchange = nullptr;
std::shared_ptr<WpaController> m_controller;
WpaEventToken m_event_token;
};
#endif //__WIFI_TELEMETRY_SOURCE_WPA_HPP__

Просмотреть файл

@ -0,0 +1,34 @@
#ifndef __WIFI_TELEMETRY_SOURCE_ZTPD_HPP__
#define __WIFI_TELEMETRY_SOURCE_ZTPD_HPP__
#include <memory>
#include <optional>
#include <sdbus-c++/sdbus-c++.h>
#include "wifi-telemetry/wifi_telemetry_source.hpp"
class __attribute__((visibility("default"))) WifiTelemetrySourceZtpd :
public WifiTelemetrySource,
public sdbus::ProxyInterfaces<sdbus::Properties_proxy>
{
public:
WifiTelemetrySourceZtpd(const std::optional<WifiInterfaceConfiguration>& interface_config);
~WifiTelemetrySourceZtpd(void);
int
activate(const std::shared_ptr<WifiTelemetrySourceActivationArgs> args) override;
void
deactivate(void) override;
private:
// sdbus::Properties_proxy
void
onPropertiesChanged(const std::string& interfaceName,
const std::map<std::string, sdbus::Variant>& changedProperties,
const std::vector<std::string>& invalidatedProperties) override;
};
#endif //__WIFI_TELEMETRY_SOURCE_ZTPD_HPP__

Просмотреть файл

@ -0,0 +1,106 @@
#ifndef __WIFI_TELEMETRY_INPUT_STATION_CONNECTION_ATTEMPT_HPP__
#define __WIFI_TELEMETRY_INPUT_STATION_CONNECTION_ATTEMPT_HPP__
#include <memory>
#include <optional>
#include "wifi-telemetry/wifi/wifi_80211.hpp"
#include "wifi-telemetry/wifi/wifi_telemetry_80211.hpp"
#include "wifi-telemetry/wpa/wpa_command_signal_poll.hpp"
#include "wifi-telemetry/wpa/wpa_command_status.hpp"
/**
* @brief Helper class that sanitizes the connection_attempt telemetry event
* inputs.
*
* Some of the input data is optional; this class checks such inputs for their
* existence/validity, and if missing/invalid, assigns defaults or appropriate
* values that the telemetry system understands as being invalid.
*/
class WifiTelemetryInputStationConnectionAttempt
{
public:
/**
* @brief Factory methods for creating instances of the correspoding
* result-type.
*
* These ensure that invalid objects are impossible to create. For example,
* if the connection attempt result was 'AssociationRejected' ALL required
* parameters must be specified for the instance to be created since no
* public constructor exists that allows construction without the required
* arguments.
*/
static WifiTelemetryInputStationConnectionAttempt
unspecified(void);
static WifiTelemetryInputStationConnectionAttempt
succeeded(const wifi_80211_mac& bssid, const std::shared_ptr<WpaCommandSignalPollResponse> signal_poll, const std::shared_ptr<WpaCommandStatusResponse> status);
static WifiTelemetryInputStationConnectionAttempt
association_rejected(const std::optional<wifi_80211_mac>& bssid, const WifiStatusCode status_code);
static WifiTelemetryInputStationConnectionAttempt
authentication_rejected(const wifi_80211_mac& bssid, const WifiStatusCode status_code, const WifiAuthenticationType authentication_type);
static WifiTelemetryInputStationConnectionAttempt
network_not_found(void);
uint32_t
result(void) const;
const char*
bssid(void) const;
const char*
ssid(void) const;
int32_t
noise(void) const;
int32_t
rssi(void) const;
int32_t
link_speed(void) const;
uint32_t
frequency(void) const;
uint32_t
wifi_generation(void) const;
const char*
key_mgmt(void) const;
const char*
pairwise_cipher(void) const;
const char*
group_cipher(void) const;
uint16_t
status_code(void) const;
const char*
authentication_type(void) const;
private:
WifiTelemetryInputStationConnectionAttempt(
const WifiConnectionAttemptResult result,
const std::optional<wifi_80211_mac> bssid,
const std::shared_ptr<WpaCommandSignalPollResponse> signal_poll,
const std::shared_ptr<WpaCommandStatusResponse> status,
const WifiStatusCode status_code,
const WifiAuthenticationType authentication_type);
const WifiConnectionAttemptResult m_result;
const std::string m_bssid;
const std::shared_ptr<WpaCommandSignalPollResponse> m_signal_poll;
const std::shared_ptr<WpaCommandStatusResponse> m_status;
const WifiStatusCode m_status_code;
const std::string m_authentication_type;
};
#endif //__WIFI_TELEMETRY_INPUT_STATION_CONNECTION_ATTEMPT_HPP__

Просмотреть файл

@ -0,0 +1,26 @@
#ifndef __WPA_COMMAND_HPP__
#define __WPA_COMMAND_HPP__
#include <cinttypes>
#include <memory>
#include <string.h>
#include <string>
#include <string_view>
#include "wifi-telemetry/wpa/wpa_command_response.hpp"
#include "wifi-telemetry/wpa/wpa_command_response_parser.hpp"
struct WpaCommand : private WpaCommandResponseParserFactory
{
WpaCommand(const std::string& name);
virtual ~WpaCommand() = default;
std::shared_ptr<WpaCommandResponse>
parse_response(const std::string_view payload) const;
const std::string name;
std::string data;
};
#endif //__WPA_COMMAND_HPP__

Просмотреть файл

@ -0,0 +1,54 @@
#ifndef __WPA_COMMAND_BSS_HPP__
#define __WPA_COMMAND_BSS_HPP__
#include <cinttypes>
#include <string>
#include <vector>
#include "wifi-telemetry/wifi/wifi_80211.hpp"
#include "wifi-telemetry/wpa/wpa_command.hpp"
#include "wifi-telemetry/wpa/wpa_command_response_parser.hpp"
struct WpaCommandBssResponseParser : public WpaCommandResponseParser
{
WpaCommandBssResponseParser(const std::string_view payload);
std::shared_ptr<WpaCommandResponse>
parse_payload(void) const override;
};
struct WpaCommandBssResponse : public WpaCommandResponse
{
WpaCommandBssResponse();
wifi_80211_mac bssid;
uint32_t id;
uint32_t capabilities;
uint32_t update_index;
uint64_t tsf;
int32_t frequency;
int32_t beacon_int;
int32_t quality;
int32_t snr;
int32_t estimated_throughput;
int32_t age;
std::string flags;
std::string ssid;
std::vector<uint8_t> ie;
std::vector<uint8_t> beacon_ie;
};
struct WpaCommandBss : public WpaCommand
{
WpaCommandBss(std::string bssid_);
WpaCommandBss(const wifi_80211_mac& bssid_);
std::string bssid;
private:
std::unique_ptr<WpaCommandResponseParser>
create_response_parser(const std::string_view payload) const override;
};
#endif // __WPA_COMMAND_BSS_HPP__

Просмотреть файл

@ -0,0 +1,32 @@
#ifndef __WPA_COMMAND_KEY_VALUE_PAIR_HPP__
#define __WPA_COMMAND_KEY_VALUE_PAIR_HPP__
#include <cstddef>
#include <optional>
#include <string_view>
struct WpaCommandKeyValuePair
{
WpaCommandKeyValuePair(const char* key_, bool is_required);
const char*
operator()(void) const;
bool
resolve(const std::string_view input);
const char* key;
const std::size_t key_length;
std::optional<const char*> value;
std::size_t value_pos;
bool is_required;
};
enum
{
WpaValueRequired = true,
WpaValueOptional = false
};
#endif //__WPA_COMMAND_KEY_VALUE_PAIR_HPP__

Просмотреть файл

@ -0,0 +1,24 @@
#ifndef __WPA_COMMAND_RESPONSE_HPP__
#define __WPA_COMMAND_RESPONSE_HPP__
#include <memory>
#include <string>
#include <string_view>
struct WpaCommandResponse
{
virtual ~WpaCommandResponse() = default;
};
/**
* @brief Used to send+receive unstructured commands+responses.
*/
struct WpaCommandResponseGeneric : public WpaCommandResponse
{
WpaCommandResponseGeneric(const std::string payload);
std::string payload;
};
#endif //__WPA_COMMAND_RESPONSE_HPP__

Просмотреть файл

@ -0,0 +1,42 @@
#ifndef __WPA_COMMAND_RESPONSE_PARSER_HPP__
#define __WPA_COMMAND_RESPONSE_PARSER_HPP__
#include <memory>
#include <optional>
#include <string_view>
#include <vector>
#include "wifi-telemetry/wpa/wpa_command_key_value_pair.hpp"
#include "wifi-telemetry/wpa/wpa_command_response.hpp"
struct WpaCommandResponseParser
{
WpaCommandResponseParser(const std::string& command_name, const std::string_view payload, const std::initializer_list<WpaCommandKeyValuePair> properties);
virtual ~WpaCommandResponseParser() = default;
virtual std::shared_ptr<WpaCommandResponse>
parse(void);
const std::string command_name;
const std::string_view payload;
protected:
virtual std::shared_ptr<WpaCommandResponse>
parse_payload(void) const = 0;
bool
resolve_properties(void);
protected:
std::vector<WpaCommandKeyValuePair> properties;
std::optional<bool> properties_resolved_result = std::nullopt;
};
struct WpaCommandResponseParserFactory
{
virtual std::unique_ptr<WpaCommandResponseParser>
create_response_parser(const std::string_view payload) const = 0;
};
#endif //__WPA_COMMAND_RESPONSE_PARSER_HPP__

Просмотреть файл

@ -0,0 +1,47 @@
#ifndef __WPA_COMMAND_SIGNAL_POLL_HPP__
#define __WPA_COMMAND_SIGNAL_POLL_HPP__
#include <cinttypes>
#include <initializer_list>
#include <memory>
#include <optional>
#include <string>
#include "wifi-telemetry/wpa/wpa_command.hpp"
#include "wifi-telemetry/wpa/wpa_command_response.hpp"
#include "wifi-telemetry/wpa/wpa_command_response_parser.hpp"
struct WpaCommandSignalPollResponseParser : public WpaCommandResponseParser
{
WpaCommandSignalPollResponseParser(const std::string_view payload);
std::shared_ptr<WpaCommandResponse>
parse_payload(void) const override;
};
struct WpaCommandSignalPollResponse : public WpaCommandResponse
{
WpaCommandSignalPollResponse(int32_t noise, int32_t rssi, int32_t link_speed, uint32_t frequency);
int32_t noise;
int32_t rssi;
int32_t link_speed;
uint32_t frequency;
std::optional<std::string> channel_width;
std::optional<int32_t> center_frequency_1 = std::nullopt;
std::optional<int32_t> center_frequency_2 = std::nullopt;
std::optional<int32_t> rssi_average = std::nullopt;
std::optional<int32_t> rssi_average_beacon = std::nullopt;
};
struct WpaCommandSignalPoll : public WpaCommand
{
WpaCommandSignalPoll(void);
private:
std::unique_ptr<WpaCommandResponseParser>
create_response_parser(const std::string_view payload) const override;
};
#endif // __WPA_COMMAND_SIGNAL_POLL_HPP__

Просмотреть файл

@ -0,0 +1,60 @@
#ifndef __WPA_COMMAND_STATUS_HPP__
#define __WPA_COMMAND_STATUS_HPP__
#include <cinttypes>
#include <string>
#include "wifi-telemetry/wifi/wifi_80211.hpp"
#include "wifi-telemetry/wpa/wpa_command.hpp"
#include "wifi-telemetry/wpa/wpa_state.hpp"
struct WpaCommandStatusResponseParser : public WpaCommandResponseParser
{
WpaCommandStatusResponseParser(const std::string_view payload);
std::shared_ptr<WpaCommandResponse>
parse_payload(void) const override;
};
struct WpaCommandStatusResponse : public WpaCommandResponse
{
WpaCommandStatusResponse(void) = default;
WpaCommandStatusResponse(WpaState state_);
WpaState state = WpaState::Unknown;
std::optional<wifi_80211_mac> bssid;
std::optional<uint32_t> frequency;
std::optional<std::string> ssid;
std::optional<std::string> passphrase;
std::optional<std::string> id_string;
std::optional<std::string> mode;
std::optional<uint32_t> wifi_generation;
std::optional<int32_t> sae_group;
std::optional<std::string> ip_address;
std::optional<std::string> p2p_address;
std::optional<std::string> address;
std::optional<int32_t> hs20;
std::optional<std::string> provisioning_sp;
std::optional<std::string> home_sp;
std::optional<std::string> sp_type;
std::optional<std::string> eap_session_id;
std::optional<std::string> uuid;
std::optional<bool> ieee80211ac;
std::optional<std::string> pairwise_cipher;
std::optional<std::string> group_cipher;
std::optional<std::string> key_mgmt;
std::optional<int32_t> pmf;
std::optional<std::string> mgmt_group_cipher;
};
struct WpaCommandStatus : public WpaCommand
{
WpaCommandStatus(void);
private:
std::unique_ptr<WpaCommandResponseParser>
create_response_parser(const std::string_view payload) const override;
};
#endif // __WPA_COMMAND_STATUS_HPP__

Просмотреть файл

@ -0,0 +1,4 @@
#include "wifi-telemetry/wpa/wpa_command_bss.hpp"
#include "wifi-telemetry/wpa/wpa_command_signal_poll.hpp"
#include "wifi-telemetry/wpa/wpa_command_status.hpp"

Просмотреть файл

@ -0,0 +1,160 @@
#ifndef __WPA_CONTROLLER_HPP__
#define __WPA_CONTROLLER_HPP__
#include <chrono>
#include <filesystem>
#include <functional>
#include <memory>
#include <mutex>
#include <optional>
#include <shared_mutex>
#include <string>
#include <string_view>
#include <thread>
#include <unordered_map>
#include <wpa_ctrl.h>
#include "wifi-telemetry/wpa/wpa_command.hpp"
#include "wifi-telemetry/wpa/wpa_command_response.hpp"
#include "wifi-telemetry/wpa/wpa_event.hpp"
#include "wifi-telemetry/wpa/wpa_event_handler.hpp"
#include "wifi-telemetry/wpa/wpa_interface_info.hpp"
typedef uint32_t WpaEventToken;
class WpaController
{
public:
WpaController(const std::string_view interface, WpaType type);
WpaController(const std::string_view interface, WpaType type, const std::string_view control_socket_path);
~WpaController(void);
/**
* @brief Registers a handler for wpa events.
*
* @param handler The handler to invoke in response to events.
* @return WpaEventToken A registration token to be used to unregister the handler.
*/
WpaEventToken
register_for_events(std::weak_ptr<WpaEventHandler> handler);
/**
* @brief Unregisters an event handler for wpa events.
*
* @param token The registration token previously obtains from register_for_events.
*/
void
unregister_for_events(WpaEventToken token);
/**
* @brief
*
* @param command
* @return std::shared_ptr<WpaControllerResponse>
*/
std::shared_ptr<WpaCommandResponse>
send_command(const WpaCommand& command);
/**
* @brief Syntactic sugar for returning a specific derived type for the response.
*
* @tparam TResponse
* @param command
* @return std::shared_ptr<TResponse>
*/
template <
typename TResponse,
typename std::enable_if<std::is_base_of<WpaCommandResponse, TResponse>::value>* = nullptr>
std::shared_ptr<TResponse>
send_command(const WpaCommand& command)
{
return std::dynamic_pointer_cast<TResponse>(send_command(command));
}
/**
* @brief Returns the type of controller
*
* @return const WpaType The type of controller.
*/
WpaType
type(void) const
{
return m_type;
}
private:
/**
* @brief Retrieves the next available message from the control socket and
* processes it.
*/
void
process_wpa_event_next(void);
/**
* @brief Waits for and processes all wpa control events.
*/
void
process_wpa_events(void);
/**
* @brief Get the command control socket object.
*
* @return struct wpa_ctrl*
*/
struct wpa_ctrl*
get_command_control_socket(void);
private:
const WpaType m_type;
std::string m_interface;
std::filesystem::path m_ctrl_socket_path;
std::thread m_ctrl_event_thread;
bool m_terminate_pending = false;
int m_ctrl_event_fd_stop = -1;
struct wpa_ctrl* m_ctrl_event = nullptr;
struct wpa_ctrl* m_ctrl_command = nullptr;
std::shared_mutex m_ctrl_command_gate;
uint32_t m_event_token_next = 0;
std::mutex m_event_subscribers_gate;
std::unordered_map<WpaEventToken, std::weak_ptr<WpaEventHandler>> m_event_subscribers;
private:
/**
* @brief Maximum wpas message size, in bytes. The wpa_cli tool uses this
* as an upper bound so is used similarly here.
*/
static constexpr std::size_t c_wpa_event_size_max = 4096;
/**
* @brief Default control socket pasth for wpa_supplicant.
*/
static constexpr std::string_view m_ctrl_socket_path_default_wpas = std::string_view("/var/run/wpa_supplicant");
/**
* @brief Default control socket pasth for hostapd.
*/
static constexpr std::string_view m_ctrl_socket_path_default_hostapd = std::string_view("/var/run/hostapd");
/**
* @brief Determines default control socket path for each wpa service type.
*
* @param type The type of wpa service to determine the default control socket for.
* @return constexpr std::string_view A string describing the default control sock path.
*/
static constexpr std::string_view
default_control_socket_path(WpaType type)
{
switch (type) {
case WpaType::Hostapd:
return m_ctrl_socket_path_default_hostapd;
case WpaType::WpaSupplicant:
return m_ctrl_socket_path_default_wpas;
default:
return "";
}
}
};
#endif //__WPA_CONTROLLER_HPP__

Просмотреть файл

@ -0,0 +1,29 @@
#ifndef __WPA_EVENT_HPP__
#define __WPA_EVENT_HPP__
enum WpaEventType
{
Connected,
Disconnected,
NetworkNotFound,
AssociationRejected,
AuthenticationRejected,
DppAuthenticationInitFailure,
DppAuthenticationSucceeded,
DppConfigurationReceived,
DppConfigurationSent,
DppFailure,
DppFrameTransmitStatus,
DppChirpReceived
};
struct WpaEvent
{
WpaEvent(WpaEventType type);
WpaEventType type;
virtual ~WpaEvent() = default;
};
#endif //__WPA_EVENT_HPP__

Просмотреть файл

@ -0,0 +1,19 @@
#ifndef __WPA_EVENT_ASSOCIATION_REJECTED_HPP__
#define __WPA_EVENT_ASSOCIATION_REJECTED_HPP__
#include <optional>
#include "wifi-telemetry/wifi/wifi_80211.hpp"
#include "wifi-telemetry/wpa/wpa_event.hpp"
struct WpaEventAssociationRejected : public WpaEvent
{
WpaEventAssociationRejected(WifiStatusCode status_code);
WpaEventAssociationRejected(WifiStatusCode status_code, const wifi_80211_mac& bssid);
const WifiStatusCode status_code;
const std::optional<wifi_80211_mac> bssid = std::nullopt;
};
#endif // __WPA_EVENT_ASSOCIATION_REJECTED_HPP__

Просмотреть файл

@ -0,0 +1,17 @@
#ifndef __WPA_EVENT_AUTHENTICATION_REJECTED_HPP__
#define __WPA_EVENT_AUTHENTICATION_REJECTED_HPP__
#include "wifi-telemetry/wifi/wifi_80211.hpp"
#include "wifi-telemetry/wpa/wpa_event.hpp"
struct WpaEventAuthenticationRejected : public WpaEvent
{
WpaEventAuthenticationRejected(const wifi_80211_mac& bssid, WifiStatusCode status_code, WifiAuthenticationType authentication_type);
const wifi_80211_mac bssid;
const WifiStatusCode status_code;
const WifiAuthenticationType authentication_type;
};
#endif // __WPA_EVENT_AUTHENTICATION_REJECTED_HPP__

Просмотреть файл

@ -0,0 +1,17 @@
#ifndef __WPA_EVENT_CONNECTED_HPP__
#define __WPA_EVENT_CONNECTED_HPP__
#include <array>
#include <cinttypes>
#include "wifi-telemetry/wifi/wifi_80211.hpp"
#include "wifi-telemetry/wpa/wpa_event.hpp"
struct WpaEventConnected : public WpaEvent
{
WpaEventConnected(const wifi_80211_mac& bssid);
const wifi_80211_mac bssid;
};
#endif // __WPA_EVENT_CONNECTED_HPP__

Просмотреть файл

@ -0,0 +1,20 @@
#ifndef __WPA_EVENT_DISCONNECTED_HPP__
#define __WPA_EVENT_DISCONNECTED_HPP__
#include <array>
#include <cinttypes>
#include "wifi-telemetry/wifi/wifi_80211.hpp"
#include "wifi-telemetry/wpa/wpa_event.hpp"
struct WpaEventDisconnected : public WpaEvent
{
WpaEventDisconnected(const wifi_80211_mac& bssid_, WifiDeauthenticationReasonCode reason_code_, bool locally_generated);
const wifi_80211_mac bssid;
const WifiDeauthenticationReasonCode reason_code;
bool locally_generated = false;
};
#endif // __WPA_EVENT_DISCONNECTED_HPP__

Просмотреть файл

@ -0,0 +1,14 @@
#ifndef __WPA_EVENT_DPP_AUTH_INIT_FAILURE_HPP__
#define __WPA_EVENT_DPP_AUTH_INIT_FAILURE_HPP__
#include <string>
#include "wifi-telemetry/wpa/wpa_event_dpp_failure.hpp"
struct WpaEventDppAuthenticationInitFailure : public WpaEventDppFailure
{
WpaEventDppAuthenticationInitFailure(void);
};
#endif // __WPA_EVENT_DPP_AUTH_INIT_FAILURE_HPP__

Просмотреть файл

@ -0,0 +1,13 @@
#ifndef __WPA_EVENT_DPP_AUTH_SUCCESS_HPP__
#define __WPA_EVENT_DPP_AUTH_SUCCESS_HPP__
#include "wifi-telemetry/wpa/wpa_event.hpp"
struct WpaEventDppAuthenticationSucceeded : public WpaEvent
{
WpaEventDppAuthenticationSucceeded(int initiator);
int initiator;
};
#endif // __WPA_EVENT_DPP_AUTH_SUCCESS_HPP__

Просмотреть файл

@ -0,0 +1,19 @@
#ifndef __WPA_EVENT_DPP_CHIRP_RECEIVED_HPP__
#define __WPA_EVENT_DPP_CHIRP_RECEIVED_HPP__
#include <cinttypes>
#include "wifi-telemetry/wifi/wifi_80211.hpp"
#include "wifi-telemetry/wpa/wpa_event.hpp"
struct WpaEventDppChirpReceived : public WpaEvent
{
WpaEventDppChirpReceived(int32_t id, const wifi_80211_mac& bssid, unsigned int frequency);
int32_t id;
wifi_80211_mac bssid;
uint32_t frequency;
};
#endif // __WPA_EVENT_DPP_CHIRP_RECEIVED_HPP__

Просмотреть файл

@ -0,0 +1,12 @@
#ifndef __WPA_EVENT_DPP_CONF_RECEIVED_HPP__
#define __WPA_EVENT_DPP_CONF_RECEIVED_HPP__
#include "wifi-telemetry/wpa/wpa_event.hpp"
struct WpaEventDppConfigurationReceived : public WpaEvent
{
WpaEventDppConfigurationReceived(void);
};
#endif // __WPA_EVENT_DPP_CONF_RECEIVED_HPP__

Просмотреть файл

@ -0,0 +1,12 @@
#ifndef __WPA_EVENT_DPP_CONF_SENT_HPP__
#define __WPA_EVENT_DPP_CONF_SENT_HPP__
#include "wifi-telemetry/wpa/wpa_event.hpp"
struct WpaEventDppConfigurationSent : public WpaEvent
{
WpaEventDppConfigurationSent(void);
};
#endif // __WPA_EVENT_DPP_CONF_SENT_HPP__

Просмотреть файл

@ -0,0 +1,22 @@
#ifndef __WPA_EVENT_DPP_FAILURE_HPP__
#define __WPA_EVENT_DPP_FAILURE_HPP__
#include <string>
#include "wifi-telemetry/wifi/wifi_dpp.hpp"
#include "wifi-telemetry/wpa/wpa_event.hpp"
struct WpaEventDppFailure : public WpaEvent
{
WpaEventDppFailure(const std::string& failure_details = "");
WpaEventDppFailure(WifiDppFailureType failure_type, const std::string& failure_details = "");
WifiDppFailureType failure_type;
const std::string failure_details;
protected:
WpaEventDppFailure(WpaEventType type, WifiDppFailureType failure_type, const std::string& failure_details = "");
};
#endif // __WPA_EVENT_DPP_FAILURE_HPP__

Просмотреть файл

@ -0,0 +1,20 @@
#ifndef __WPA_EVENT_DPP_FRAME_TRANSMIT_STATUS_HPP__
#define __WPA_EVENT_DPP_FRAME_TRANSMIT_STATUS_HPP__
#include <cinttypes>
#include <string>
#include "wifi-telemetry/wifi/wifi_80211.hpp"
#include "wifi-telemetry/wpa/wpa_event.hpp"
struct WpaEventDppFrameTransmitStatus : public WpaEvent
{
WpaEventDppFrameTransmitStatus(const wifi_80211_mac& destination_bssid, unsigned int frequency, const std::string& status);
wifi_80211_mac destination_bssid;
uint32_t frequency;
std::string status;
};
#endif // __WPA_EVENT_DPP_FRAME_TRANSMIT_STATUS_HPP__

Просмотреть файл

@ -0,0 +1,68 @@
#ifndef __WPA_EVENT_HANDLER_HPP__
#define __WPA_EVENT_HANDLER_HPP__
#include <chrono>
#include <memory>
#include "wifi-telemetry/wpa/wpa_events.hpp"
template <typename T>
struct WpaEventArgs
{
WpaEventArgs(std::chrono::time_point<std::chrono::system_clock> timestamp_, std::shared_ptr<T> event_) :
timestamp(timestamp_),
event(event_)
{}
std::chrono::time_point<std::chrono::system_clock> timestamp;
std::shared_ptr<T> event;
const T&
data() const
{
return *event;
}
};
class WpaEventHandler
{
public:
virtual void
on_connected(const WpaEventArgs<WpaEventConnected>& args);
virtual void
on_disconnected(const WpaEventArgs<WpaEventDisconnected>& args);
virtual void
on_association_rejected(const WpaEventArgs<WpaEventAssociationRejected>& args);
virtual void
on_authentication_rejected(const WpaEventArgs<WpaEventAuthenticationRejected>& args);
virtual void
on_network_not_found(const WpaEventArgs<WpaEventNetworkNotFound>& args);
virtual void
on_dpp_chirp_received(const WpaEventArgs<WpaEventDppChirpReceived>& args);
virtual void
on_dpp_frame_transmit_status(const WpaEventArgs<WpaEventDppFrameTransmitStatus>& args);
virtual void
on_dpp_authentication_init_failure(const WpaEventArgs<WpaEventDppAuthenticationInitFailure>& args);
virtual void
on_dpp_authentication_succeeded(const WpaEventArgs<WpaEventDppAuthenticationSucceeded>& args);
virtual void
on_dpp_configuration_received(const WpaEventArgs<WpaEventDppConfigurationReceived>& args);
virtual void
on_dpp_configuration_sent(const WpaEventArgs<WpaEventDppConfigurationSent>& args);
virtual void
on_dpp_failure(const WpaEventArgs<WpaEventDppFailure>& args);
};
#endif //__WPA_EVENT_HANDLER_HPP__

Просмотреть файл

@ -0,0 +1,12 @@
#ifndef __WPA_EVENT_NETWORK_NOT_FOUND_HPP__
#define __WPA_EVENT_NETWORK_NOT_FOUND_HPP__
#include "wifi-telemetry/wpa/wpa_event.hpp"
struct WpaEventNetworkNotFound : public WpaEvent
{
WpaEventNetworkNotFound(void);
};
#endif // __WPA_EVENT_NETWORK_NOT_FOUND_HPP__

Просмотреть файл

@ -0,0 +1,14 @@
#include "wifi-telemetry/wpa/wpa_event.hpp"
#include "wifi-telemetry/wpa/wpa_event_association_rejected.hpp"
#include "wifi-telemetry/wpa/wpa_event_authentication_rejected.hpp"
#include "wifi-telemetry/wpa/wpa_event_connected.hpp"
#include "wifi-telemetry/wpa/wpa_event_disconnected.hpp"
#include "wifi-telemetry/wpa/wpa_event_dpp_auth_init_failure.hpp"
#include "wifi-telemetry/wpa/wpa_event_dpp_auth_success.hpp"
#include "wifi-telemetry/wpa/wpa_event_dpp_chirp_received.hpp"
#include "wifi-telemetry/wpa/wpa_event_dpp_conf_received.hpp"
#include "wifi-telemetry/wpa/wpa_event_dpp_conf_sent.hpp"
#include "wifi-telemetry/wpa/wpa_event_dpp_failure.hpp"
#include "wifi-telemetry/wpa/wpa_event_dpp_frame_transmit_status.hpp"
#include "wifi-telemetry/wpa/wpa_event_network_not_found.hpp"

Просмотреть файл

@ -0,0 +1,38 @@
#ifndef __WPA_INTERFACE_INFO_HPP__
#define __WPA_INTERFACE_INFO_HPP__
#include <stdexcept>
#include <string>
#include "wifi-telemetry/wifi/wifi_common.hpp"
enum WpaType
{
Hostapd,
WpaSupplicant
};
/**
* @brief Interface information common to all interfaces and modes.
*/
struct WpaInterfaceInfo
{
std::string name;
std::string address;
static constexpr WpaType
TypeFromOperationalMode(WifiOperationalMode mode)
{
switch (mode) {
case WifiOperationalMode::Station:
return WpaType::WpaSupplicant;
case WifiOperationalMode::AccessPoint:
return WpaType::Hostapd;
default:
throw new std::invalid_argument("no WpaType for operational mode");
}
}
};
#endif // __WPA_INTERFACE_INFO_HPP__

Просмотреть файл

@ -0,0 +1,25 @@
#ifndef __WPA_STATE_HPP__
#define __WPA_STATE_HPP__
#include <cinttypes>
enum class WpaState : uint32_t
{
Unknown = 0,
Disconnected = 1,
InterfaceDisabled = 2,
Inactive = 3,
Scanning = 4,
Authenticating = 5,
Associating = 6,
Associated = 7,
FourWayHandshake = 8,
GroupHandshake = 9,
Completed = 10
};
WpaState
wpa_state_from_string(const char* state);
#endif //__WPA_STATE_HPP__

Просмотреть файл

@ -0,0 +1,101 @@
#!/bin/bash
set -euf -o pipefail
TEMPDIR=
DEBUG=
FEATURE=wifi-telemetry
REDIRECT=/dev/null
GIT_REPO_DEFAULT="git@github.com:microsoft/wifi-telemetry.git"
RELEASE_BRANCH_SOURCE_DEFAULT="main"
function usage() {
echo "$0 -v <version number> [-b <release source branch name>] [-r <git repo url>] [-f] [-d]"
echo
echo " -v <version number>"
echo " The numerical version, in semver format, of the release."
echo " Eg. 0.3.5"
echo " -b <release source branch name>"
echo " The name of the branch from which release source should be obtained."
echo " (default=${RELEASE_BRANCH_SOURCE_DEFAULT})"
echo " -r <git repo url>"
echo " The git repo url to use."
echo " (default=${GIT_REPO_DEFAULT}"
echo " -f"
echo " Determines whether or not release tags should be forcibly pushed."
echo " Note that this will overwrite any existing tags; use with caution."
echo " (default=disabled)"
echo " -d"
echo " Enable script debugging. This enables script output (stdout+stderr)."
echo
}
function finish() {
if [ ! -z ${TEMPDIR+x} ]; then
rm -rf ${TEMPDIR} >& ${REDIRECT}
fi
}
function main() {
local RELEASE_VERSION=
local RELEASE_BRANCH_SOURCE=${RELEASE_BRANCH_SOURCE_DEFAULT}
local FORCE=
local GIT_REPO=${GIT_REPO_DEFAULT}
while getopts ":v:b:r:fd" opt; do
case ${opt} in
v)
RELEASE_VERSION="${OPTARG}"
;;
b)
RELEASE_BRANCH_SOURCE="${OPTARG}"
;;
r)
GIT_REPO="${OPTARG}"
;;
f)
FORCE=" -f"
;;
d)
DEBUG=1
REDIRECT=/dev/tty
;;
*)
;;
esac
done
if [ -z ${RELEASE_VERSION+x} ]; then
echo "missing release version"
usage
exit 1
fi
local RELEASE_VERSION_TAG=v${RELEASE_VERSION}
local RELEASE_NAME=${FEATURE}-${RELEASE_VERSION}
local RELEASE_DIR_SOURCE=${FEATURE}-release-${RELEASE_VERSION}
local RELEASE_DIR=${RELEASE_NAME}
local RELEASE_ARCHIVE=${RELEASE_NAME}
TEMPDIR=$(mktemp -d)
pushd ${TEMPDIR} >& ${REDIRECT}
echo "checking out branch '${RELEASE_BRANCH_SOURCE}' from ${GIT_REPO}"
git clone ${GIT_REPO} --branch ${RELEASE_BRANCH_SOURCE} ${RELEASE_DIR_SOURCE} >& ${REDIRECT}
pushd ${RELEASE_DIR_SOURCE} >& ${REDIRECT}
echo "tagging as ${RELEASE_VERSION_TAG}"
git tag ${RELEASE_VERSION_TAG} ${FORCE} >& ${REDIRECT}
git push origin refs/tags/${RELEASE_VERSION_TAG} ${FORCE} >& ${REDIRECT}
popd >& ${REDIRECT}
echo "preparing release archive"
git clone --depth 1 --branch ${RELEASE_VERSION_TAG} ${GIT_REPO} ${RELEASE_DIR} >& ${REDIRECT}
pushd ${RELEASE_DIR} >& ${REDIRECT}
rm -rf .vscode .git .gitignore >& ${REDIRECT}
popd >& ${REDIRECT}
popd >& ${REDIRECT}
tar cJf ${PWD}/${RELEASE_NAME}.tar.xz -C ${TEMPDIR} ${RELEASE_DIR} >& ${REDIRECT}
echo "created release archive ${RELEASE_NAME}.tar.xz -> $(sha256sum ${RELEASE_NAME}.tar.xz | awk '{print $1}')"
}
main "$@"
finish

14
src/CMakeLists.txt Normal file
Просмотреть файл

@ -0,0 +1,14 @@
install(
EXPORT wifi-telemetry-targets
NAMESPACE wifi-telemetry::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wifi-telemetry
)
install(
FILES "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/wifi-telemetry-config.cmake"
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wifi-telemetry
)
add_subdirectory(daemon)
add_subdirectory(lib)

35
src/daemon/CMakeLists.txt Normal file
Просмотреть файл

@ -0,0 +1,35 @@
add_executable(wifi-telemetryd
""
)
set_property(
TARGET wifi-telemetryd
PROPERTY POSITION_INDEPENDENT_CODE TRUE
)
install(
TARGETS wifi-telemetryd
DESTINATION ${CMAKE_INSTALL_SBINDIR}
)
target_sources(wifi-telemetryd
PRIVATE
main.cxx
)
target_include_directories(wifi-telemetryd
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/../../include
)
target_link_libraries(wifi-telemetryd
PRIVATE
wifi-telemetry
INTERFACE
${LIBSYSTEMD_TARGET}
${LIBWPA_CLIENT_TARGET}
)
add_subdirectory(systemd)

118
src/daemon/main.cxx Normal file
Просмотреть файл

@ -0,0 +1,118 @@
#include <getopt.h>
#include <iostream>
#include <signal.h>
#include <stdexcept>
#include <string.h>
#include <string>
#include "wifi-telemetry/wifi_telemetry_monitor.hpp"
#include "wifi-telemetry/wifi_telemetry_source_wpa.hpp"
#include "wifi-telemetry/wifi_telemetry_source_ztpd.hpp"
static char*
triml(char* s)
{
while (isspace(*s))
s++;
return s;
}
static WifiOperationalMode
parse_wifi_operational_mode(const char* operational_mode)
{
if (strcmp(operational_mode, "ap") == 0 ||
strcmp(operational_mode, "access-point") == 0) {
return WifiOperationalMode::AccessPoint;
} else if (strcmp(operational_mode, "sta") == 0 ||
strcmp(operational_mode, "station") == 0) {
return WifiOperationalMode::Station;
}
throw new std::invalid_argument("invalid operational mode string");
}
struct WifiTelemetrySourceArgs
{
explicit WifiTelemetrySourceArgs(const std::string& name_) :
name(name_)
{}
std::string name;
std::optional<std::string> interface;
std::optional<WifiOperationalMode> operational_mode;
};
int
main(int argc, char* argv[])
{
WifiTelemetryMonitor monitor{};
WifiTelemetrySourceArgs* source_active = nullptr;
std::vector<WifiTelemetrySourceArgs> sources{};
for (;;) {
int opt = getopt(argc, argv, "i:o:s:");
if (opt < 0)
break;
switch (opt) {
case 'i':
if (source_active)
source_active->interface = triml(optarg);
break;
case 'o':
if (source_active)
source_active->operational_mode = parse_wifi_operational_mode(triml(optarg));
break;
case 's':
source_active = &sources.emplace_back(triml(optarg));
break;
default:
break;
}
}
if (sources.size() == 0) {
std::cerr << "no sources added" << std::endl;
return -1;
}
for (const auto& source : sources) {
// prepare interface configuration, if specified
std::optional<WifiInterfaceConfiguration> interface;
if (source.interface.has_value()) {
interface.emplace(source.interface.value());
if (source.operational_mode.has_value())
interface->operational_mode = source.operational_mode.value();
}
// add the source
if (source.name == "wpa")
monitor.add_source<WifiTelemetrySourceWpa>(interface);
else if (source.name == "ztp")
monitor.add_source<WifiTelemetrySourceZtpd>(interface);
}
monitor.start();
// Mask SIGTERM and SIGINT so they can be explicitly waited on from the main thread.
int signal;
sigset_t mask;
sigemptyset(&mask);
sigaddset(&mask, SIGTERM);
sigaddset(&mask, SIGINT);
if (sigprocmask(SIG_BLOCK, &mask, nullptr) < 0) {
std::cerr << "failed to block terminate signals" << std::endl;
return -1;
}
// Wait for the process to be signaled to exit.
while (sigwait(&mask, &signal) != 0)
;
// Received interrupt or terminate signal, so shutdown.
monitor.stop();
return 0;
}

Просмотреть файл

@ -0,0 +1,23 @@
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/wifi-telemetryd-ap@.service.in
${CMAKE_CURRENT_BINARY_DIR}/wifi-telemetryd-ap@.service
)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/wifi-telemetryd-station@.service.in
${CMAKE_CURRENT_BINARY_DIR}/wifi-telemetryd-station@.service
)
configure_file(
${CMAKE_CURRENT_SOURCE_DIR}/wifi-telemetryd-ztp.service.in
${CMAKE_CURRENT_BINARY_DIR}/wifi-telemetryd-ztp.service
)
install(
FILES
${CMAKE_CURRENT_BINARY_DIR}/wifi-telemetryd-ap@.service
${CMAKE_CURRENT_BINARY_DIR}/wifi-telemetryd-station@.service
${CMAKE_CURRENT_BINARY_DIR}/wifi-telemetryd-ztp.service
DESTINATION ${CMAKE_INSTALL_LIBDIR}/systemd/system
)

Просмотреть файл

@ -0,0 +1,9 @@
[Unit]
Description=Wi-Fi Telemetry Daemon (WPA Access Point)
Requires=sys-subsystem-net-devices-%i.device
After=sys-subsystem-net-devices-%i.device
[Service]
Type=simple
Restart=on-failure
ExecStart=${CMAKE_INSTALL_FULL_SBINDIR}/wifi-telemetryd -s wpa -o ap -i %i

Просмотреть файл

@ -0,0 +1,9 @@
[Unit]
Description=Wi-Fi Telemetry Daemon (WPA Station)
Requires=sys-subsystem-net-devices-%i.device
After=sys-subsystem-net-devices-%i.device
[Service]
Type=simple
Restart=on-failure
ExecStart=${CMAKE_INSTALL_FULL_SBINDIR}/wifi-telemetryd -s wpa -o station -i %i

Просмотреть файл

@ -0,0 +1,7 @@
[Unit]
Description=Wi-Fi Telemetry Daemon (Zero Touch Provisioning)
[Service]
Type=simple
Restart=on-failure
ExecStart=${CMAKE_INSTALL_FULL_SBINDIR}/wifi-telemetryd -s ztp

48
src/lib/CMakeLists.txt Normal file
Просмотреть файл

@ -0,0 +1,48 @@
add_library(wifi-telemetry
SHARED
""
)
if (BUILD_HOSTAP_EXTERNAL)
add_dependencies(wifi-telemetry hostap)
endif()
target_include_directories(wifi-telemetry
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/../../include
)
target_link_libraries(wifi-telemetry
INTERFACE
${LIBSYSTEMD_TARGET}
${LIBWPA_CLIENT_TARGET}
udev
pci
)
target_sources(wifi-telemetry
PRIVATE
wifi_device_info.cxx
wifi_telemetry_monitor.cxx
wifi_telemetry_source.cxx
wifi_telemetry_instance_impl.cxx
wifi_telemetry_source_wpa.cxx
wifi_telemetry_source_ztpd.cxx
../../include/wifi-telemetry/wifi/wifi_80211_format_mac.hpp
)
add_subdirectory(wpa)
add_subdirectory(lttng-providers)
add_subdirectory(ztpd)
install(
TARGETS wifi-telemetry
EXPORT wifi-telemetry-targets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
)
install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../../include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
)

Просмотреть файл

@ -0,0 +1,28 @@
target_sources(wifi-telemetry
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/wifi_telemetry_lttng_provider_station.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wifi_telemetry_lttng_provider_dpp.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wifi_telemetry_lttng_provider_wifi.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wifi_telemetry_trace_dpp.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wifi_telemetry_trace_station.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wifi_telemetry_trace_wifi.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wifi_telemetry_trace.cxx
)
target_include_directories(wifi-telemetry
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
target_link_libraries(wifi-telemetry
INTERFACE
LTTng::UST
)
if (ENABLE_MS_LTTNG_EXTENSIONS)
target_link_libraries(wifi-telemetry
PRIVATE
tracelogging::tracelogging
)
endif()

Просмотреть файл

@ -0,0 +1,5 @@
#define TRACEPOINT_DEFINE
#define TRACEPOINT_CREATE_PROBES
#include "wifi_telemetry_lttng_provider_dpp.hpp"

Просмотреть файл

@ -0,0 +1,326 @@
#undef TRACEPOINT_PROVIDER
#define TRACEPOINT_PROVIDER wifi_dpp
#undef TRACEPOINT_INCLUDE
#define TRACEPOINT_INCLUDE "./wifi_telemetry_lttng_provider_dpp.hpp"
#if !defined(__WIFI_TELEMETRY_LTTNG_PROVIDER_DPP_HPP__) || defined(TRACEPOINT_HEADER_MULTI_READ)
#define _TRACEPOINT_LTTNG_UST_TRACEF_PROVIDER_H
#define __WIFI_TELEMETRY_LTTNG_PROVIDER_DPP_HPP__
#include <lttng/tracepoint.h>
#include <stddef.h>
#include <stdint.h>
/**
* @brief Event for a completed Device Provisioning Protocol (DPP) enrollee
* exchange.
*
* This event fires each time a DPP exchange completes with the host device
* acting as the enrollee device role. The event has a state which describes
* the furthest state of the exchange reached, which is a relative indication
* of success or failure.
*
* See the telemetry field descriptions below to determine which fields are
* valid for specific state values.
*/
TRACEPOINT_EVENT(
wifi_dpp,
dpp_exchange_enrollee,
TP_ARGS(
const char *, interface,
const char *, state,
const char *, role,
uint64_t, duration_milliseconds,
size_t, chirp_frequencies_count,
const uint32_t *, chirp_frequencies,
const char *, failure_type,
const char *, failure_details
),
TP_FIELDS(
/**
* @brief Interface name [required].
*
* This fields describes the name of the wireless interface. It is
* always included in the telemetry event. The interface may be virtual
* or physical; no indication is provided in the event.
*
* The data is formatted as a free-form string, consisting of
* printable ASCII characters.
*
* @example wlan0
* @example wlp4s0
*/
ctf_string(interface, interface)
/**
* @brief The last/furthest state of the dpp exchange reached [required].
*
* This field describes the furthest state of the dpp exchange reached.
* The exchange was successful if the terminal state was entered,
* indicated by the value "provisioned". The following are the possible
* values:
*
* - bootstrapping
* This is the initial state.
* - authenticated
* This state is entered once bootstrapping has completed.
* - provisioning
* This state is entered once the dpp peer has been successfully
* authenticated.
* - provisioned
* This state is entered once the enrollee has received a network
* configuration object.
* - terminated
* This state is erntered if an error occurs during the exchange. In
* this case, the 'failure_type' and 'failure_details' fields provide
* more information about the cause of the failure.
*/
ctf_string(state, state)
/**
* @brief DPP exchange role [required].
*
* This field indicates the DPP role of the host, either initiator or
* responder.
*
* The following strings are the possible values of this field:
*
* - initiator
* - responder
*/
ctf_string(role, role)
/**
* @brief Exchange duration (milliseconds) [required].
*
* This fields describes the duration of the DPP exchange, in
* milliseconds.
*
* The exchange is started when the first presence announcement (chirp)
* is transmitted and completes when either a timeout occurs, an error
* is encountered, or the enrollee is successfully provisioned.
*
* @example 2100
*/
ctf_integer(uint64_t, duration_milliseconds, duration_milliseconds)
/**
* @brief Exchange presence announcement (chirp) frequencies [required].
*
* This field describes all the frequencies where presence announcement
* frames were sent. This is an additive, unique list that includes
* every such frequency chirped, even if the last iteration of chirping
* did not include a particular frequency.
*
* The chirp frequencies are encoded as an array of 32-bit unsigned
* integers.
*/
ctf_sequence(uint32_t, chirp_frequencies, chirp_frequencies, size_t, chirp_frequencies_count)
/**
* @brief The DPP failure type [conditional].
*
* This field describes the category of failure that occurred if the
* exchange failed. This field is only valid when the state field has
* the value "terminated".
*
* The following strings are the possible values of this field:
*
* - none
* This occurs when there was no error.
* - unspecified
* This occurs when the error is not known.
* - authentication-timeout
* This occurs when the DPP peer took too long to respond to the
* authentication request frame.
*/
ctf_string(failure_type, failure_type)
/**
* @brief DPP failure details [conditional].
*
* This field describes additional details regarding the cause of the
* failure. This field is only valid when the state field has the value
* "terminated". It is a free-form string.
*/
ctf_string(failure_details, failure_details)))
/**
* @brief Event for a complete dpp configurator exchange.
*/
TRACEPOINT_EVENT(
wifi_dpp,
dpp_exchange_configurator,
TP_ARGS(
const char *, interface,
const char *, state,
const char *, role,
uint64_t, duration_milliseconds,
const char *, bssid,
uint32_t, frequency,
const char *, failure_type,
const char *, failure_details
),
TP_FIELDS(
/**
* @brief Interface name [required].
*
* This fields describes the name of the wireless interface. It is
* always included in the telemetry event. The interface may be virtual
* or physical; no indication is provided in the event.
*
* The data is formatted as a free-form string, consisting of
* printable ASCII characters.
*
* @example wlan0
* @example wlp4s0
*/
ctf_string(interface, interface)
/**
* @brief The last/furthest state of the dpp exchange reached [required].
*
* This field describes the furthest state of the dpp exchange reached.
* The exchange was successful if the terminal state was entered,
* indicated by the value "finished". The following are the possible
* values:
*
* - bootstrapping
* This is the initial state.
* - authenticated
* This state is entered once bootstrapping has completed.
* - finished
* This state is entered once the configurator has sent a network
* configuration object to the enrollee.
* - terminated
* This state is erntered if an error occurs during the exchange. In
* this case, the 'failure_type' and 'failure_details' fields provide
* more information about the cause of the failure.
*/
ctf_string(state, state)
/**
* @brief DPP exchange role [required].
*
* This field indicates the DPP role of the host, either initiator or
* responder.
*
* The following strings are the possible values of this field:
*
* - initiator
* - responder
*/
ctf_string(role, role)
/**
* @brief Exchange duration (milliseconds) [required].
*
* This fields describes the duration of the DPP exchange, in
* milliseconds.
*
* The exchange is started when the first presence announcement (chirp)
* is received and completes when either a timeout occurs, an error
* is encountered, or a network configuration object is sent to the
* enrollee.
*
* @example 2100
*/
ctf_integer(uint64_t, duration_milliseconds, duration_milliseconds)
/**
* @brief The Basic Service Set Identifier (BSSID) of the enrollee
* [required].
*
* This field describes the BSSID of the enrollee involved in the
* exchange.
*
* The data is formatted as a 48-bit sequence of hexadecimal pairs,
* separated by a colon (:).
*
* @example 70:66:55:09:b6:6f
* @example 72:66:55:27:2c:1b
*/
ctf_string(bssid, bssid)
/**
* @brief The radio frequency used for the exchange (MHz) [optional].
*
* This field describes the radio frequency used for the exchange. This
* field is always valid for all state field values except
* 'bootstrapping', for which it is optionally valid. A value of zero
* (0) indicates the field is invalid and should be ignored.
*
* @example 2412
* @example 5180
*/
ctf_integer(uint32_t, frequency, frequency)
/**
* @brief The DPP failure type [conditional].
*
* This field describes the category of failure that occurred if the
* exchange failed. This field is only valid when the state field has
* the value "terminated".
*
* The following strings are the possible values of this field:
*
* - none
* This occurs when there was no error.
* - unspecified
* This occurs when the error is not known.
* - authentication-timeout
* This occurs when the DPP peer took too long to respond to the
* authentication request frame.
*/
ctf_string(failure_type, failure_type)
/**
* @brief DPP failure details [conditional].
*
* This field describes additional details regarding the cause of the
* failure. This field is only valid when the state field has the value
* "terminated". It is a free-form string.
*/
ctf_string(failure_details, failure_details)))
/**
* @brief Event for Device Provisioning Protocol device role change.
*
* This event fires any time the active DPP device roles change on the host.
* The event reports the currently active device roles (not the device role
* that changed disposition).
*/
TRACEPOINT_EVENT(
wifi_dpp,
dpp_device_roles_changed,
TP_ARGS(
const char*, device_roles),
TP_FIELDS(
/**
* @brief Active Device Provisioning Protocol (DPP) device roles
* [required].
*
* This field describes the currently active DPP device roles. There
* are two possible values:
*
* - enrollee
* - configurator
*
* This field is encoded as a single string using the comma (,) as a
* delimeter for each active device role, with no additional spaces
* separating the delimeter and subsequent role(s). The string may be
* empty or contain any combination of the above values in any order.
*
* @example enrollee,configurator
* @example enrollee
* @example configurator
* @example configurator,enrollee
*/
ctf_string(device_roles, device_roles)))
#endif // !defined(__WIFI_TELEMETRY_LTTNG_PROVIDER_DPP_HPP__) || defined(TRACEPOINT_HEADER_MULTI_READ)
#include <lttng/tracepoint-event.h>

Просмотреть файл

@ -0,0 +1,5 @@
#define TRACEPOINT_DEFINE
#define TRACEPOINT_CREATE_PROBES
#include "wifi_telemetry_lttng_provider_station.hpp"

Просмотреть файл

@ -0,0 +1,387 @@
#undef TRACEPOINT_PROVIDER
#define TRACEPOINT_PROVIDER wifi_station
#undef TRACEPOINT_INCLUDE
#define TRACEPOINT_INCLUDE "./wifi_telemetry_lttng_provider_station.hpp"
#if !defined(__WIFI_TELEMETRY_LTTNG_PROVIDER_STATION_HPP__) || defined(TRACEPOINT_HEADER_MULTI_READ)
#define _TRACEPOINT_LTTNG_UST_TRACEF_PROVIDER_H
#define __WIFI_TELEMETRY_LTTNG_PROVIDER_STATION_HPP__
#include <lttng/tracepoint.h>
#include <stddef.h>
#include <stdint.h>
#include "wifi-telemetry/wpa/wifi_telemetry_input_station_connection_attempt.hpp"
/**
* @brief Event for a connection attempt from a wifi station (client) to an
* access point or other peer.
*
* This event fires upon completion of all connection attempts. The attempt has
* a result which describes whether it was successful, and result-specific
* fields that further describe details of the result; connection state
* information when succesful, and failure details otherwise.
*
* See the telemetry field descriptions below to determine which fields are
* valid for specific result values.
*/
TRACEPOINT_EVENT(
wifi_station,
connection_attempt,
TP_ARGS(
const char*, interface,
const WifiTelemetryInputStationConnectionAttempt*, data),
TP_FIELDS(
/**
* @brief Interface name [required].
*
* This fields describes the name of the wireless interface. It is
* always included in the telemetry event. The interface may be virtual
* or physical; no indication is provided in the event.
*
* The data is formatted as a free-form string, consisting of
* printable ASCII characters.
*
* @example wlan0
* @example wlp4s0
*/
ctf_string(interface, interface)
/**
* @brief The result of the connection attempt [required].
*
* This field describes the coarse result of the connection attempt.
*
* The data is formatted as an unsigned, 32-bit integer. @see
* WifiConnectionAttemptResult for a complete list of all possible
* values this field can take.
*
* result values and sub-fields:
*
* - WifiConnectionAttemptResult::Succeeded (value=0)
* This result occurs when the connection attempt was successful and a
* valid connection was made. In this case, the following telemetry
* fields will further describe the state of the connection:
*
* - bssid
* - ssid
* - rssi
* - noise
* - link_speed
* - frequency
* - wifi_generation
* - key_mgmt
* - group_cipher
*
* - WifiConnectionAttemptResult::Unspecified (value=1)
* This result occurs when the connection attempt failed and no
* specific reason for the failure could be determined. No additional
* fields are valid for this result value.
*
* - WifiConnectionAttemptResult::AuthenticationRejected (value=2)
* This result occurs when the connection attempt failed due to
* authentication being rejected by the peer. In this case, the
* following telemetry fields in this event will further describe the
* reason for failure:
*
* - bssid
* - status_code
* - authentication_type
*
* The status code field describes the specific reason for failure.
* See the comments in status code for more details. The
* autnentication type field describes the type of authentication
* attempted.
*
* - WifiConnectionAttemptResult::AssociationRejected (value=3)
* This result occurs when the connection attempt failed due to
* association being rejected. In this case, the following telemetry
* fields in this event will further describe the reason for failure:
*
* - bssid
* - status_code
*
* The status code field describes the specific reason for failure. See
* the comments in status code for more details.
*
* - WifiConnectionAttemptResult::NetworkNotFound:
* This result occurs whenm the connection attempt failed due to the
* selected network not being found. This can occur when either the
* target network is not in radio range, or when the target network was
* found but does not match the characteristics of its profile. For
* example, this can occur when the network profile specifies the
* target network uses one type of authentication, but the actual
* network uses a different type. In this case, no additional telemetry
* fields are valid.
*/
ctf_integer(uint32_t, result, data->result())
/**
* @brief The Basic Service Set Identifier (BSSID) of the connection
* attempt peer [conditional].
*
* This field describes the BSSID of the wireless device peer involved
* in the connection attempt.
*
* The data is formatted as a 48-bit sequence of hexadecimal pairs,
* separated by a colon (:).
*
* @example 70:66:55:09:b6:6f
* @example 72:66:55:27:2c:1b
*/
ctf_string(bssid, data->bssid())
/**
* @brief The Service Set Identifier (SSID) of the peer [conditional].
*
* This field describes the SSID of the wireless device peer involved
* in the connection attempt.
*
* @example My Home Network
* @example Microsoft-Guest
*/
ctf_string(ssid, data->ssid())
/**
* @brief Connection Received Signal Strength Indicator (RSSI) [conditional].
*
* This field describes the RSSI of the connection at the time
* the connection was established. This is technically a unit-less
* value, however, is typically reported in dBm. RSSI units and values
* are vendor specific and so should not be compared across vendors and
* in some cases, even different devices.
*
* This field is only valid when result == 0 (Succeeded) and is
* otherwise undefined and must be discarded.
*
* @example -70
* @example 10
*/
ctf_integer(int32_t, rssi, data->rssi())
/**
* @brief Connection noise level (dB) [conditional].
*
* This fields describes the noise level of the connection at the time
* the connection was established. The unit is decibels (dB).
*
* This field is only valid when result == 0 (Succeeded) and is
* otherwise undefined and must be discarded.
*/
ctf_integer(int32_t, noise, data->noise())
/**
* @brief Connection link speed (Mbps) [conditional].
*
* This fields describes the link speed of the connection at the time
* the connection was established. The unit is Mbps.
*
* This field is only valid when result == 0 (Succeeded) and is
* otherwise undefined and must be discarded.
*/
ctf_integer(int32_t, link_speed, data->link_speed())
/**
* @brief Connection frequency (MHz) [conditional].
*
* This field describes the frequency of the connection at the time the
* connection was established. The unit is MHz.
*
* This field is only valid when result == 0 (Succeeded) and is
* otherwise undefined and must be discarded.
*/
ctf_integer(uint32_t, frequency, data->frequency())
/**
* @brief Connection Wi-Fi generation [conditional].
*
* This field describes the numerical Wi-Fi generation of the
* connection. This corresponds to specific IEEE Wi-Fi standards,
* starting with 802.11n (4), 802.11ac (5), 802.11ax (6).
*
* This field is only valid when result == 0 (Succeeded) and is
* otherwise undefined and must be discarded.
*/
ctf_integer(uint32_t, wifi_generation, data->wifi_generation())
/**
* @brief Connection key management [conditional].
*
* This field describes the key management method used by the
* connection. The following strings are some of the possible values:
*
* - NONE
* - WPA-NONE
* - IEEE 802.1X (no WPA)
* - FT-EAP
* - FT-EAP-SHA384
* - FT-PSK
* - WPA2-EAP-SHA256
* - WPA2-PSK-SHA256
* - WPS
* - SAE
* - FT-SAE
* - OSEN
* - WPA2-EAP-SUITE-B
* - WPA2-EAP-SUITE-B-192
* - FILS-SHA256
* - FILS-SHA384
* - FT-FILS-SHA256
* - FT-FILS-SHA384
* - OWE
* - DPP
* - UNKNOWN
*
* This field is only valid when result == 0 (Succeeded) and is
* otherwise undefined and must be discarded.
*/
ctf_string(key_mgmt, data->key_mgmt())
/**
* @brief Connection pairwise cipher [conditional].
*
* This fields describes the connection pairwise cipher. The pairwise
* cipher is used for unicast (point-to-point) traffic.
*
* The following strings are some of the possible values:
* - NONE
* - WEP-40
* - WEP-104
* - TKIP
* - CCMP
* - CCMP+TKIP
* - GCMP
* - GCMP-256
* - CCMP-256
* - BIP
* - BIP-GMAC-128
* - BIP-GMAC-256
* - BIP-CMAC-256
* - GTK_NOT_USED
* - UNKNOWN
*
* This field is only valid when result == 0 (Succeeded) and is
* otherwise undefined and must be discarded.
*/
ctf_string(pairwise_cipher, data->pairwise_cipher())
/**
* @brief Connection group cipher [conditional].
*
* This fields describes the connection group cipher. The group cipher
* is used for multicast traffic.
*
* The possible values are the same as pairwise_cipher.
*
* This field is only valid when result == 0 (Succeeded) and is
* otherwise undefined and must be discarded.
*/
ctf_string(group_cipher, data->group_cipher())
/**
* @brief The Wi-Fi status code of the connection attempt [conditional].
*
* This fields describes the Wi-Status code of the connection attempt.
* The values are defined in IEEE Std 802.11-2016, Section 9.4.1.9,
* Table 9-46. @see WifiStatusCode for a more detailed description.
*
* This field is only valid when:
* result == 2 (AuthenticationRejected) OR
* result == 3 (AssociationRejected)
* and is otherwise undefined and must be discarded
*/
ctf_integer(uint16_t, status_code, data->status_code())
/**
* @brief The connection authentication type [conditional].
*
* This field describes the general authentication type of the
* connnection attempt.
*
* The following strings are some of the possible values:
*
* - unknown
* - open
* - wpa-psk
* - shared
* - wpa
* - wpa2
* - wpa2-psk
*
* This field is only valid when result == 2
* (AuthenticationRejected) and is otherwise undefined and must be
* discarded.
*/
ctf_string(authentication_type, data->authentication_type())))
/**
* @brief Event for a connection drop from an access point or other wireless peer.
*
* This event fires any time an established wireless connection is severred or
* dropped, regardless of whether it was a healthy/expected disconnection or an
* unhealthy/unexpected one.
*/
TRACEPOINT_EVENT(
wifi_station,
connection_drop,
TP_ARGS(
const char*, interface,
const char*, bssid,
uint16_t, reason_code,
int, locally_generated),
TP_FIELDS(
/**
* @brief Interface name [required].
*
* This fields describes the name of the wireless interface. It is
* always included in the telemetry event. The interface may be virtual
* or physical; no indication is provided in the event.
*
* The data is formatted as a free-form string, consisting of
* printable ASCII characters.
*
* @example wlan0
* @example wlp4s0
*/
ctf_string(interface, interface)
/**
* @brief The Basic Service Set Identifier (BSSID) of the connection
* attempt peer [required].
*
* This field describes the BSSID of the wireless device peer that was
* disconnected.
*
* The data is formatted as a 48-bit sequence of hexadecimal pairs,
* separated by a colon (:).
*
* @example 70:66:55:09:b6:6f
* @example 72:66:55:27:2c:1b
*/
ctf_string(bssid, bssid)
/**
* @brief The reason code for disassociation [required].
*
* This field describes the reason for disassociation (connection
* drop). The values are defined in IEEE Std 802.11-2016, Section
* 9.4.1.4, Table 9-45. @see WifiDeauthenticationReasonCode for a more
* detailed description.
*/
ctf_integer(uint16_t, reason_code, reason_code)
/**
* @brief Local generation/request indicator [required].
*
* This field describes whether the connection drop originated from the
* client (locally_generated != 0) or originated from the peer
* (locally_generated == 0).
*/
ctf_integer(int, locally_generated, locally_generated)))
#endif // !defined(__WIFI_TELEMETRY_LTTNG_PROVIDER_STATION_HPP__) || defined(TRACEPOINT_HEADER_MULTI_READ
#include <lttng/tracepoint-event.h>

Просмотреть файл

@ -0,0 +1,5 @@
#define TRACEPOINT_DEFINE
#define TRACEPOINT_CREATE_PROBES
#include "wifi_telemetry_lttng_provider_wifi.hpp"

Просмотреть файл

@ -0,0 +1,164 @@
#undef TRACEPOINT_PROVIDER
#define TRACEPOINT_PROVIDER wifi
#undef TRACEPOINT_INCLUDE
#define TRACEPOINT_INCLUDE "./wifi_telemetry_lttng_provider_wifi.hpp"
#if !defined(__WIFI_TELEMETRY_LTTNG_PROVIDER_WIFI_HPP__) || defined(TRACEPOINT_HEADER_MULTI_READ)
#define _TRACEPOINT_LTTNG_UST_TRACEF_PROVIDER_H
#define __WIFI_TELEMETRY_LTTNG_PROVIDER_WIFI_HPP__
#include <lttng/tracepoint.h>
#include <stddef.h>
#include <stdint.h>
#include "wifi_device_info.hpp"
/**
* @brief Event for wifi device/chipset information.
*
* This event fires periodically to report information about the wifi chipset
* and driver being used for a particular interface. The event will fire each
* start() is called on a WifiTelemetryMonitor instance. All telemetry events
* generated from the monitor can then be associated with the device
* information reported at the beginning of the session.
*/
TRACEPOINT_EVENT(
wifi,
device_info,
TP_ARGS(
const struct WifiDeviceInfo*, device),
TP_FIELDS(
/**
* @brief Interface name [required].
*
* This fields describes the name of the wireless interface. It is
* always included in the telemetry event. The interface may be virtual
* or physical; no indication is provided in the event.
*
* The data is formatted as a free-form string, consisting of
* printable ASCII characters.
*
* @example wlan0
* @example wlp4s0
*/
ctf_string(interface, device->interface.c_str())
/**
* @brief Wi-Fi Basic Service Set Identifier (BSSID) [required].
*
* This field describes the BSSID of the wireless device, which
* uniquely identifies an 802.11-based wireless device.
*
* The data is formatted as a 48-bit sequence of hexadecimal pairs,
* separated by a colon (:).
*
* @example 70:66:55:09:b6:6f
* @example 72:66:55:27:2c:1b
*/
ctf_string(bssid, device->bssid.c_str())
/**
* @brief Device subsystem [required].
*
* This fields describes the kernel subsystem that is used to host the
* device. This typically describes the device's bus.
*
* The data is formatted as a free-form string, consisting of printable
* ASCII characters.
*
* @example pci
* @example usb
*/
ctf_string(subsystem, device->subsystem.c_str())
/**
* @brief Kernel driver (module) name [required].
*
* This field describes the name of the kernel driver (module) used to
* control the device.
*
* The data is formatted as a free-form string, consisting of printable
* ASCII characters.
*
* @example ath10k
* @example rtl88x2ce
*/
ctf_string(kernel_driver, device->kernel_driver.c_str())
/**
* @brief Kernel driver (module) version [required].
*
* This fields describes the version string of the kernel driver
* (module). Each module may define this string arbitrarily; it may
* contain numerical version information.
*
* The data is formatted as a free-form string, consisting of printable
* ASCII characters.
*
* @example v5.9.0.3_36433.20200310_COEX20200103-1717
*/
ctf_string(kernel_driver_version, device->kernel_driver_version.c_str())
/**
* @brief Device vendor name [optional].
*
* This fields describes the vendor of the device.
*
* The data is formatted as a free-form string, consisting of printable
* ASCII characters.
*
* @example Intel Corporation
* @example Realtek Semiconductor Co., Ltd.
*/
ctf_string(vendor, device->vendor.value_or("").c_str())
/**
* @brief Device model name [optional].
*
* This fields describes the device name or model of the device,
* differentiating it from other devices manufactured by the vendor.
*
* The data is formatted as a free-form string, consisting of printable
* ASCII characters.
*
* @example Device c822
*/
ctf_string(device, device->device.value_or("").c_str())
/**
* @brief Device subsystem vendor [optional].
*
* This field describes the name of the subsystem-specific vendor of
* the device. This can be different from the device vendor field when
* the bus portion of the device is implemented using different IHV
* hardware components.
*
* The data is formatted as a free-form string, consisting of printable
* ASCII characters.
*
* @example AzureWave
*/
ctf_string(subsystem_vendor, device->subsystem_vendor.value_or("").c_str())
/**
* @brief Device subsystem model name [optional].
*
* This field describes the name of the subsystem-specific vendor of
* the device, differentiating it from other devices manufactured by
* the subsystem vendor. This can be different from the device model
* field when the bus potion of the device is implemented using
* different IHV hardware components.
*
* The data is formatted as a free-form string, consisting of printable
* ASCII characters.
* @example Device 3750
*/
ctf_string(subsystem_device, device->subsystem_device.value_or("").c_str())))
#endif // !defined(__WIFI_TELEMETRY_LTTNG_PROVIDER_WIFI_HPP__) || defined(TRACEPOINT_HEADER_MULTI_READ)
#include <lttng/tracepoint-event.h>

Просмотреть файл

@ -0,0 +1,29 @@
#include "wifi_telemetry_trace.hpp"
#include "wifi_telemetry_trace_dpp.hpp"
#include "wifi_telemetry_trace_station.hpp"
#include "wifi_telemetry_trace_wifi.hpp"
#ifdef TRACE_USE_TRACELOGGING
#include "wifi_telemetry_tracelogging.hpp"
#endif // !TRACE_USE_TRACELOGGING
void
WifiTelemetryTraceProvider::RegisterAll(void)
{
#ifdef TRACE_USE_TRACELOGGING
TraceLoggingRegister(g_TraceloggingProviderWifi);
TraceLoggingRegister(g_TraceloggingProviderWifiDpp);
TraceLoggingRegister(g_TraceloggingProviderWifiStation);
#endif
}
void
WifiTelemetryTraceProvider::UnregisterAll(void)
{
#ifdef TRACE_USE_TRACELOGGING
TraceLoggingUnregister(g_TraceloggingProviderWifi);
TraceLoggingUnregister(g_TraceloggingProviderWifiDpp);
TraceLoggingUnregister(g_TraceloggingProviderWifiStation);
#endif
}

Просмотреть файл

@ -0,0 +1,21 @@
#ifndef __WIFI_TELEMETRY_TRACE_HPP__
#define __WIFI_TELEMETRY_TRACE_HPP__
struct WifiTelemetryTraceProvider
{
/**
* @brief Registers all Tracelogging-based providers with LLTNG. This must
* be called prior to generating any tracelogging-based telemetry events.
*/
static void
RegisterAll(void);
/**
* @brief Unregisters all Tracelogging-based providers from LTTNG.
*/
static void
UnregisterAll(void);
};
#endif //__WIFI_TELEMETRY_TRACEPROVIDERS_HPP__

Просмотреть файл

@ -0,0 +1,91 @@
#include "wifi_telemetry_trace_dpp.hpp"
#include "wifi_telemetry_lttng_provider_dpp.hpp"
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc99-extensions"
#pragma clang diagnostic ignored "-Wgnu-statement-expression"
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#endif //__clang__
#ifdef TRACE_USE_TRACELOGGING
// Provider UUID: 91adedb1-4f70-405f-9771-00415a5e375e
TRACELOGGING_DEFINE_PROVIDER(
g_TraceloggingProviderWifiDpp,
"Microsoft.Azure.Device.Wifi.Dpp",
(0x91adedb1, 0x4f70, 0x405f, 0x97, 0x71, 0x00, 0x41, 0x5a, 0x5e, 0x37, 0x5e));
#endif // !TRACE_USE_TRACELOGGING
void
trace_dpp_exchange_enrollee(const char* interface, const char* state, const char* role, uint64_t duration_milliseconds, size_t chirp_frequencies_count, const uint32_t* chirp_frequencies, const char* failure_type, const char* failure_details)
{
#ifdef TRACE_USE_TRACELOGGING
TraceLoggingWrite(g_TraceloggingProviderWifiDpp,
"DppExchangeEnrollee",
TraceLoggingString(interface, "interface"),
TraceLoggingString(state, "exchangeState"),
TraceLoggingString(role, "dppDeviceRole"),
TraceLoggingUInt64(duration_milliseconds, "durationMilliseconds"),
TraceLoggingUInt32Array(chirp_frequencies, static_cast<uint16_t>(chirp_frequencies_count), "chirpFrequenciesMhz"),
TraceLoggingString(failure_type, "failureType"),
TraceLoggingString(failure_details, "failureDetails"));
#else // TRACE_USE_TRACELOGGING
tracepoint(wifi_dpp,
dpp_exchange_enrollee,
interface,
role,
state,
duration_milliseconds,
chirp_frequencies_count,
chirp_frequencies,
failure_type,
failure_details);
#endif // !TRACE_USE_TRACELOGGING
}
void
trace_dpp_exchange_configurator(const char* interface, const char* state, const char* role, uint64_t duration_milliseconds, const char* bssid, uint32_t frequency, const char* failure_type, const char* failure_details)
{
#ifdef TRACE_USE_TRACELOGGING
TraceLoggingWrite(g_TraceloggingProviderWifiDpp,
"DppExchangeConfigurator",
TraceLoggingString(interface, "interface"),
TraceLoggingString(state, "exchangeState"),
TraceLoggingString(role, "dppDeviceRole"),
TraceLoggingUInt64(duration_milliseconds, "durationMilliseconds"),
TraceLoggingString(bssid, "bssid"),
TraceLoggingUInt32(frequency, "frequencyMHz"),
TraceLoggingString(failure_type, "failureType"),
TraceLoggingString(failure_details, "failureDetails"));
#else // TRACE_USE_TRACELOGGING
tracepoint(wifi_dpp,
dpp_exchange_configurator,
interface,
role,
state,
duration_milliseconds,
bssid,
frequency,
failure_type,
failure_details);
#endif // !TRACE_USE_TRACELOGGING
}
void
trace_dpp_device_roles_changed(const char* device_roles)
{
#ifdef TRACE_USE_TRACELOGGING
TraceLoggingWrite(g_TraceloggingProviderWifiDpp,
"DppDeviceRolesChanged",
TraceLoggingString(device_roles, "dppDeviceRolesActive"));
#else // TRACE_USE_TRACELOGGING
tracepoint(wifi_dpp,
dpp_device_roles_changed,
device_roles);
#endif // !TRACE_USE_TRACELOGGING
}
#ifdef __clang__
#pragma clang diagnostic pop
#endif //__clang__

Просмотреть файл

@ -0,0 +1,25 @@
#ifndef __WIFI_TELEMETRY_TRACE_DPP_HPP__
#define __WIFI_TELEMETRY_TRACE_DPP_HPP__
#include <cstdint>
#include <cstddef>
#ifdef TRACE_USE_TRACELOGGING
#include "wifi_telemetry_tracelogging.hpp"
#endif // !TRACE_USE_TRACELOGGING
#ifdef TRACE_USE_TRACELOGGING
TRACELOGGING_DECLARE_PROVIDER(g_TraceloggingProviderWifiDpp);
#endif // !TRACE_USE_TRACELOGGING
void
trace_dpp_exchange_enrollee(const char* interface, const char* state, const char* role, uint64_t duration_milliseconds, size_t chirp_frequencies_count, const uint32_t* chirp_frequencies, const char* failure_type, const char* failure_details);
void
trace_dpp_exchange_configurator(const char* interface, const char* state, const char* role, uint64_t duration_milliseconds, const char* bssid, uint32_t frequency, const char* failure_type, const char* failure_details);
void
trace_dpp_device_roles_changed(const char* device_roles);
#endif //__WIFI_TELEMETRY_TRACE_DPP_HPP__

Просмотреть файл

@ -0,0 +1,70 @@
#include "wifi_telemetry_trace_station.hpp"
#include "wifi_telemetry_lttng_provider_station.hpp"
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc99-extensions"
#pragma clang diagnostic ignored "-Wgnu-statement-expression"
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#endif //__clang__
#ifdef TRACE_USE_TRACELOGGING
// Provider UUID: 00bb2910-064f-41b3-8ead-ad6d608a10d0
TRACELOGGING_DEFINE_PROVIDER(
g_TraceloggingProviderWifiStation,
"Microsoft.Azure.Device.Wifi.Station",
(0x00bb2910, 0x064f, 0x41b3, 0x8e, 0xad, 0xad, 0x6d, 0x60, 0x8a, 0x10, 0xd0));
#endif // !TRACE_USE_TRACELOGGING
void
trace_station_connection_attempt(const char* interface, const WifiTelemetryInputStationConnectionAttempt* data)
{
#ifdef TRACE_USE_TRACELOGGING
TraceLoggingWrite(g_TraceloggingProviderWifiStation,
"ConnectionAttempt",
TraceLoggingString(interface, "interface"),
TraceLoggingUInt32(data->result(), "result"),
TraceLoggingString(data->bssid(), "bssid"),
TraceLoggingString(data->ssid(), "ssid"),
TraceLoggingInt32(data->rssi(), "rssi"),
TraceLoggingInt32(data->noise(), "noiseDb"),
TraceLoggingInt32(data->link_speed(), "linkSpeedMbps"),
TraceLoggingUInt32(data->frequency(), "frequencyMHz"),
TraceLoggingUInt32(data->wifi_generation(), "wifiGeneration"),
TraceLoggingString(data->key_mgmt(), "keyManagement"),
TraceLoggingString(data->pairwise_cipher(), "pairwiseCipher"),
TraceLoggingString(data->group_cipher(), "groupCipher"),
TraceLoggingUInt16(data->status_code(), "statusCode"),
TraceLoggingString(data->authentication_type(), "authenticationType"));
#else // TRACE_USE_TRACELOGGING
tracepoint(wifi_station,
connection_attempt,
interface,
data);
#endif // !TRACE_USE_TRACELOGGING
}
void
trace_station_connection_drop(const char* interface, const char* bssid, uint16_t reason_code, int locally_generated)
{
#ifdef TRACE_USE_TRACELOGGING
TraceLoggingWrite(g_TraceloggingProviderWifiStation,
"ConnectionDrop",
TraceLoggingString(interface, "interface"),
TraceLoggingString(bssid, "bssid"),
TraceLoggingUInt16(reason_code, "reasonCode"),
TraceLoggingBoolean(!!locally_generated, "locallyGenerated"));
#else // TRACE_USE_TRACELOGGING
tracepoint(wifi_station,
connection_drop,
interface,
bssid,
reason_code,
locally_generated);
#endif // !TRACE_USE_TRACELOGGING
}
#ifdef __clang__
#pragma clang diagnostic pop
#endif //__clang__

Просмотреть файл

@ -0,0 +1,20 @@
#ifndef __WIFI_TELEMETRY_TRACE_STATION_HPP__
#define __WIFI_TELEMETRY_TRACE_STATION_HPP__
#ifdef TRACE_USE_TRACELOGGING
#include "wifi_telemetry_tracelogging.hpp"
#endif // !TRACE_USE_TRACELOGGING
#include "wifi-telemetry/wpa/wifi_telemetry_input_station_connection_attempt.hpp"
#ifdef TRACE_USE_TRACELOGGING
TRACELOGGING_DECLARE_PROVIDER(g_TraceloggingProviderWifiStation);
#endif // !TRACE_USE_TRACELOGGING
void
trace_station_connection_attempt(const char *interface, const WifiTelemetryInputStationConnectionAttempt *data);
void
trace_station_connection_drop(const char *interface, const char *bssid, uint16_t reason_code, int locally_generated);
#endif //__WIFI_TELEMETRY_TRACE_STATION_HPP__

Просмотреть файл

@ -0,0 +1,44 @@
#include "wifi_telemetry_trace_wifi.hpp"
#include "wifi_telemetry_lttng_provider_wifi.hpp"
#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc99-extensions"
#pragma clang diagnostic ignored "-Wgnu-statement-expression"
#pragma clang diagnostic ignored "-Wgnu-zero-variadic-macro-arguments"
#endif //__clang__
#ifdef TRACE_USE_TRACELOGGING
// Provider UUID: d4238472-0bb9-4b64-af1e-14f3f7a5411b
TRACELOGGING_DEFINE_PROVIDER(
g_TraceloggingProviderWifi,
"Microsoft.Azure.Device.Wifi",
(0xd4238472, 0x0bb9, 0x4b64, 0xaf, 0x1e, 0x14, 0xf3, 0xf7, 0xa5, 0x41, 0x1b));
#endif // !TRACE_USE_TRACELOGGING
void
trace_wifi_device_info(const struct WifiDeviceInfo* device)
{
#ifdef TRACE_USE_TRACELOGGING
TraceLoggingWrite(g_TraceloggingProviderWifi,
"DeviceInfo",
TraceLoggingString(device->interface.c_str(), "interface"),
TraceLoggingString(device->bssid.c_str(), "bssid"),
TraceLoggingString(device->subsystem.c_str(), "subsystem"),
TraceLoggingString(device->kernel_driver.c_str(), "kernelDriver"),
TraceLoggingString(device->kernel_driver_version.c_str(), "kernelDriverVersion"),
TraceLoggingString(device->vendor.value_or("").c_str(), "vendor"),
TraceLoggingString(device->device.value_or("").c_str(), "model"),
TraceLoggingString(device->subsystem_vendor.value_or("").c_str(), "subsystemVendor"),
TraceLoggingString(device->subsystem_device.value_or("").c_str(), "subsystemModel"));
#else // TRACE_USE_TRACELOGGING
tracepoint(wifi,
device_info,
device);
#endif // !TRACE_USE_TRACELOGGING
}
#ifdef __clang__
#pragma clang diagnostic pop
#endif //__clang__

Просмотреть файл

@ -0,0 +1,17 @@
#ifndef __WIFI_TELEMETRY_TRACEPROVIDER_WIFI_HPP__
#define __WIFI_TELEMETRY_TRACEPROVIDER_WIFI_HPP__
#include "wifi_device_info.hpp"
#ifdef TRACE_USE_TRACELOGGING
#include "wifi_telemetry_tracelogging.hpp"
#endif // !TRACE_USE_TRACELOGGING
#ifdef TRACE_USE_TRACELOGGING
TRACELOGGING_DECLARE_PROVIDER(g_TraceloggingProviderWifi);
#endif // !TRACE_USE_TRACELOGGING
void
trace_wifi_device_info(const struct WifiDeviceInfo* info);
#endif //__WIFI_TELEMETRY_TRACEPROVIDER_WIFI_HPP__

Просмотреть файл

@ -0,0 +1,22 @@
/**
* This file should be used in place of #include'ing TraceLoggingProvider.h
* directly because it re-defines as macros what LTTNG has defined as an enum
* :-(
*/
#include <tracelogging/TraceLoggingProvider.h>
#undef TRACE_EMERG
#undef TRACE_ALERT
#undef TRACE_CRIT
#undef TRACE_ERR
#undef TRACE_WARNING
#undef TRACE_NOTICE
#undef TRACE_INFO
#undef TRACE_DEBUG_SYSTEM
#undef TRACE_DEBUG_PROGRAM
#undef TRACE_DEBUG_PROCESS
#undef TRACE_DEBUG_MODULE
#undef TRACE_DEBUG_UNIT
#undef TRACE_DEBUG_FUNCTION
#undef TRACE_DEBUG_LINE
#undef TRACE_DEBUG

Просмотреть файл

@ -0,0 +1,131 @@
#include <cstdlib>
#include <filesystem>
#include <libudev.h>
#include <stdexcept>
#include <string.h>
extern "C" {
#include <pci/pci.h>
}
#include "wifi_device_info.hpp"
WifiDeviceInfo::WifiDeviceInfo(
const std::string& interface_,
const std::string& bssid_,
const std::string& subsystem_,
const std::string& kernel_driver_,
const std::string& kernel_driver_version_) :
interface(interface_),
bssid(bssid_),
subsystem(subsystem_),
kernel_driver(kernel_driver_),
kernel_driver_version(kernel_driver_version_)
{}
static uint16_t
hexstr_to_uint16(const char *str)
{
if (!str)
return 0;
unsigned long value = strtoul(str, nullptr, 16);
if (value > UINT16_MAX)
value = 0;
return static_cast<uint16_t>(value);
}
static void
fill_ids_pci(WifiDeviceInfo& device_info, struct udev_device *parent)
{
const char *vendor_str = udev_device_get_sysattr_value(parent, "vendor");
const char *device_str = udev_device_get_sysattr_value(parent, "device");
const char *subsystem_device_str = udev_device_get_sysattr_value(parent, "subsystem_device");
const char *subsystem_vendor_str = udev_device_get_sysattr_value(parent, "subsystem_vendor");
uint16_t vendor = hexstr_to_uint16(vendor_str);
uint16_t device = hexstr_to_uint16(device_str);
uint16_t svendor = hexstr_to_uint16(subsystem_vendor_str);
uint16_t sdevice = hexstr_to_uint16(subsystem_device_str);
struct pci_access *pacc = pci_alloc();
char pci_vendor[128];
char pci_device[128];
char pci_svendor[128];
char pci_sdevice[128];
pci_init(pacc);
device_info.vendor = pci_lookup_name(pacc, pci_vendor, sizeof pci_vendor, PCI_LOOKUP_VENDOR, vendor, device);
device_info.device = pci_lookup_name(pacc, pci_device, sizeof pci_device, PCI_LOOKUP_DEVICE, vendor, device);
device_info.subsystem_vendor = pci_lookup_name(pacc, pci_svendor, sizeof pci_svendor, PCI_LOOKUP_VENDOR | PCI_LOOKUP_SUBSYSTEM, svendor);
device_info.subsystem_device = pci_lookup_name(pacc, pci_sdevice, sizeof pci_sdevice, PCI_LOOKUP_DEVICE | PCI_LOOKUP_SUBSYSTEM, vendor, device, svendor, sdevice);
pci_cleanup(pacc);
}
static void
fill_ids_generic(WifiDeviceInfo& device_info, struct udev_device *parent)
{
const char *vendor = udev_device_get_property_value(parent, "ID_VENDOR_FROM_DATABASE");
const char *model = udev_device_get_property_value(parent, "ID_MODEL_FROM_DATABASE");
if (!vendor)
vendor = udev_device_get_property_value(parent, "ID_VENDOR");
if (!model)
model = udev_device_get_property_value(parent, "ID_MODEL");
if (vendor)
device_info.vendor = vendor;
if (model)
device_info.device = model;
}
static void
fill_ids(WifiDeviceInfo& device_info, struct udev_device *parent)
{
if (device_info.subsystem == "pci")
fill_ids_pci(device_info, parent);
else
fill_ids_generic(device_info, parent);
}
WifiDeviceInfo
WifiDeviceInfo::from_interface(const std::string& interface)
{
const std::filesystem::path sysfs_path = std::filesystem::path("/sys/class/net") / interface;
struct udev *udev = udev_new();
struct udev_device *device = udev_device_new_from_syspath(udev, sysfs_path.c_str());
if (!device)
throw new std::invalid_argument(std::string("invalid sysfs path ") + sysfs_path.c_str());
// Ensure this is a wireless device.
const char *devtype = udev_device_get_devtype(device);
if (!devtype || strcmp(devtype, "wlan") != 0)
throw new std::invalid_argument(interface + " is not a wireless device");
struct udev_device *device_parent = udev_device_get_parent(device);
const char *kernel_driver_syspath = udev_device_get_syspath(device_parent);
const std::filesystem::path sysfs_path_kmodule = std::filesystem::path(kernel_driver_syspath) / "driver/module";
struct udev_device *device_module = udev_device_new_from_syspath(udev, sysfs_path_kmodule.c_str());
if (!device_module)
throw new std::invalid_argument("unable to obtain device kernel module");
const char *address = udev_device_get_sysattr_value(device, "address");
const char *subsystem = udev_device_get_subsystem(device_parent);
const char *kernel_driver = udev_device_get_driver(device_parent);
const char *kernel_driver_version = udev_device_get_sysattr_value(device_module, "version");
WifiDeviceInfo device_info { interface, address, subsystem, kernel_driver, kernel_driver_version };
fill_ids(device_info, device_parent);
udev_device_unref(device_module);
udev_device_unref(device_parent);
udev_device_unref(device);
udev_unref(udev);
return device_info;
}

Просмотреть файл

@ -0,0 +1,32 @@
#ifndef __WIFI_DEVICE_INFO_HPP__
#define __WIFI_DEVICE_INFO_HPP__
#include <optional>
#include <string>
struct WifiDeviceInfo
{
WifiDeviceInfo(
const std::string& interface,
const std::string& bssid,
const std::string& subsystem,
const std::string& kernel_driver,
const std::string& kernel_driver_version);
const std::string interface;
const std::string bssid;
const std::string subsystem;
const std::string kernel_driver;
const std::string kernel_driver_version;
std::optional<std::string> vendor;
std::optional<std::string> device;
std::optional<std::string> subsystem_vendor;
std::optional<std::string> subsystem_device;
static WifiDeviceInfo
from_interface(const std::string& interface);
};
#endif // __WIFI_DEVICE_INFO_HPP__

Просмотреть файл

@ -0,0 +1,29 @@
#include "wifi_telemetry_instance_impl.hpp"
WifiTelemetrySourceInstanceImpl::WifiTelemetrySourceInstanceImpl(std::shared_ptr<WifiTelemetrySource> source_, const std::shared_ptr<WifiTelemetrySourceActivationArgs> args_) :
WifiTelemetrySourceInstance(source_, args_)
{}
int
WifiTelemetrySourceInstanceImpl::activate(void)
{
if (m_activated)
return 0;
int ret = source->activate(args);
if (ret == 0)
m_activated = true;
return 0;
}
void
WifiTelemetrySourceInstanceImpl::deactivate(void)
{
if (!m_activated)
return;
source->deactivate();
m_activated = false;
}

Просмотреть файл

@ -0,0 +1,22 @@
#ifndef __WIFI_TELEMETRY_SOURCE_INSTANCE_IMPL_HPP__
#define __WIFI_TELEMETRY_SOURCE_INSTANCE_IMPL_HPP__
#include "wifi-telemetry/wifi_telemetry_source_instance.hpp"
struct WifiTelemetrySourceInstanceImpl :
public WifiTelemetrySourceInstance
{
WifiTelemetrySourceInstanceImpl(std::shared_ptr<WifiTelemetrySource> source, const std::shared_ptr<WifiTelemetrySourceActivationArgs> args);
int
activate(void);
void
deactivate(void);
private:
bool m_activated = false;
};
#endif // __WIFI_TELEMETRY_SOURCE_INSTANCE_IMPL_HPP__

Просмотреть файл

@ -0,0 +1,110 @@
#include <algorithm>
#include <cinttypes>
#include <iostream>
#include <unordered_set>
#include "wifi-telemetry/wifi_telemetry_monitor.hpp"
#include "wifi_device_info.hpp"
#include "wifi_telemetry_instance_impl.hpp"
#include "wifi_telemetry_trace.hpp"
#include "wifi_telemetry_trace_wifi.hpp"
WifiTelemetryMonitor::WifiTelemetryMonitor(void)
{
WifiTelemetryTraceProvider::RegisterAll();
}
WifiTelemetryMonitor::~WifiTelemetryMonitor(void)
{
WifiTelemetryTraceProvider::UnregisterAll();
}
void
WifiTelemetryMonitor::add_source_impl(const std::shared_ptr<WifiTelemetrySource> source, const std::shared_ptr<WifiTelemetrySourceActivationArgs> activation_args)
{
auto instance = std::make_unique<WifiTelemetrySourceInstanceImpl>(source, activation_args);
if (m_activated)
instance->activate();
m_sources.push_back(std::move(instance));
}
/**
* @brief Removes a telemetry source from the monitor.
*
* @param registration_token The registration token obtained from add_source().
*/
void
WifiTelemetryMonitor::remove_source(const std::shared_ptr<WifiTelemetrySource> source)
{
const auto& result = std::find_if(std::begin(m_sources), std::end(m_sources), [&](const auto& instance) {
return (instance->source == source);
});
if (result == std::end(m_sources))
return;
WifiTelemetrySourceInstanceImpl& instance = dynamic_cast<WifiTelemetrySourceInstanceImpl&>(**result);
instance.deactivate();
m_sources.erase(result);
}
std::size_t
WifiTelemetryMonitor::activate_sources(void)
{
std::size_t num_activated = 0;
std::unordered_set<std::string> interfaces;
for (auto& instance : m_sources) {
int ret = dynamic_cast<WifiTelemetrySourceInstanceImpl&>(*instance).activate();
if (ret < 0) {
std::cerr << "failed to activate telemetry source '" << instance->source->name() << "' (" << ret << ")" << std::endl;
continue;
}
// Generate a telemetry event for each unique interface being monitored.
if (instance->source->interface()) {
const auto& [interface, inserted] = interfaces.insert(instance->source->interface()->name);
if (inserted) {
try {
WifiDeviceInfo device_info = WifiDeviceInfo::from_interface(*interface);
trace_wifi_device_info(&device_info);
} catch (...) {
std::cout << "warning: failed to generate wifi device info telemetry event for " << *interface << std::endl;
}
}
}
num_activated++;
std::cout << "activated telemetry source '" << instance->source->name() << "'" << std::endl;
}
return num_activated;
}
void
WifiTelemetryMonitor::deactivate_sources(void)
{
for (auto& instance : m_sources) {
dynamic_cast<WifiTelemetrySourceInstanceImpl&>(*instance).deactivate();
}
}
void
WifiTelemetryMonitor::start(void)
{
std::size_t num_activated_desired = m_sources.size();
std::size_t num_activated_actual = activate_sources();
std::cout << "telemetry monitor started with " << num_activated_actual << " of " << num_activated_desired
<< " telemetry sources" << std::endl;
m_activated = true;
}
void
WifiTelemetryMonitor::stop(void)
{
deactivate_sources();
m_activated = false;
}

Просмотреть файл

@ -0,0 +1,36 @@
#include "wifi-telemetry/wifi_telemetry_source.hpp"
WifiTelemetrySource::WifiTelemetrySource(const std::optional<WifiInterfaceConfiguration>& interface) :
m_interface(interface)
{}
WifiTelemetrySource::WifiTelemetrySource(const std::optional<WifiInterfaceConfiguration>& interface, const std::string& name) :
m_name(name),
m_interface(interface)
{}
WifiTelemetrySource::~WifiTelemetrySource(void)
{}
int
WifiTelemetrySource::activate(const std::shared_ptr<WifiTelemetrySourceActivationArgs> /* args */)
{
return 0;
}
void
WifiTelemetrySource::deactivate(void)
{}
const std::string_view
WifiTelemetrySource::name(void) const
{
return m_name;
}
const std::optional<WifiInterfaceConfiguration>&
WifiTelemetrySource::interface(void) const
{
return m_interface;
}

Просмотреть файл

@ -0,0 +1,358 @@
#include <iostream>
#include <sstream>
#include <stdexcept>
#include "wifi-telemetry/wifi/wifi_80211_format_mac.hpp"
#include "wifi-telemetry/wifi_telemetry_source_wpa.hpp"
#include "wifi-telemetry/wpa/wpa_commands.hpp"
#include "wifi_telemetry_trace_dpp.hpp"
#include "wifi_telemetry_trace_station.hpp"
WifiTelemetrySourceWpa::WifiTelemetrySourceWpa(const std::optional<WifiInterfaceConfiguration>& interface) :
WifiTelemetrySource(interface, "wpa")
{
if (!interface.has_value())
throw new std::invalid_argument("WifiTelemetrySourceWpa requires interface configuration, but none was supplied");
}
WifiTelemetrySourceWpa::~WifiTelemetrySourceWpa(void)
{
if (m_controller) {
m_controller->unregister_for_events(m_event_token);
m_controller = nullptr;
}
}
int
WifiTelemetrySourceWpa::activate(const std::shared_ptr<WifiTelemetrySourceActivationArgs> /* args */)
{
WpaType type = WpaInterfaceInfo::TypeFromOperationalMode(m_interface->operational_mode);
m_controller = std::make_unique<WpaController>(m_interface->name, type);
m_event_token = m_controller->register_for_events(weak_from_this());
return 0;
}
void
WifiTelemetrySourceWpa::deactivate(void)
{
m_controller = nullptr;
}
bool
WifiTelemetrySourceWpa::trace_station(void) const
{
return (m_interface->operational_mode == WifiOperationalMode::Station);
}
bool
WifiTelemetrySourceWpa::trace_ap(void) const
{
return (m_interface->operational_mode == WifiOperationalMode::AccessPoint);
}
bool
WifiTelemetrySourceWpa::trace_dpp_enrollee(void) const
{
// right now, assume all enrollees are wifi stations.
return trace_station();
}
bool
WifiTelemetrySourceWpa::trace_dpp_configurator(void) const
{
// right now, assume all configurators are wifi access points.
return trace_ap();
}
bool
WifiTelemetrySourceWpa::trace_dpp(void) const
{
return trace_dpp_enrollee() || trace_dpp_configurator();
}
bool
WifiTelemetrySourceWpa::is_dpp_exchange_in_progress(void) const
{
return (m_dpp_exchange != nullptr);
}
void
WifiTelemetrySourceWpa::on_disconnected(const WpaEventArgs<WpaEventDisconnected>& args)
{
if (!trace_station())
return;
const auto& event = args.data();
std::string bssid = wifi_80211_mac_to_string(event.bssid);
trace_station_connection_drop(
m_interface->name.c_str(),
bssid.c_str(),
uint16_t(event.reason_code),
event.locally_generated);
}
void
WifiTelemetrySourceWpa::complete_connection_attempt(const WifiTelemetryInputStationConnectionAttempt& input)
{
trace_station_connection_attempt(m_interface->name.c_str(), &input);
}
void
WifiTelemetrySourceWpa::on_connected(const WpaEventArgs<WpaEventConnected>& args)
{
if (!trace_station())
return;
const auto& event = args.data();
struct WpaCommandSignalPoll signal_poll{};
auto response_signal_poll = m_controller->send_command<WpaCommandSignalPollResponse>(signal_poll);
if (!response_signal_poll) {
std::cerr << "unable to obtain signal poll data" << std::endl;
return;
}
struct WpaCommandStatus command_status{};
auto response_status = m_controller->send_command<WpaCommandStatusResponse>(command_status);
if (!response_status) {
std::cerr << "unable to obtain interface status data" << std::endl;
return;
}
auto connection_attempt_data = WifiTelemetryInputStationConnectionAttempt::succeeded(
event.bssid,
response_signal_poll,
response_status);
complete_connection_attempt(connection_attempt_data);
}
void
WifiTelemetrySourceWpa::on_association_rejected(const WpaEventArgs<WpaEventAssociationRejected>& args)
{
if (!trace_station())
return;
const auto& event = args.data();
auto connection_attempt_data = WifiTelemetryInputStationConnectionAttempt::association_rejected(
event.bssid,
event.status_code);
complete_connection_attempt(connection_attempt_data);
}
void
WifiTelemetrySourceWpa::on_authentication_rejected(const WpaEventArgs<WpaEventAuthenticationRejected>& args)
{
if (!trace_station())
return;
const auto& event = args.data();
auto connection_attempt_data = WifiTelemetryInputStationConnectionAttempt::authentication_rejected(
event.bssid,
event.status_code,
event.authentication_type);
complete_connection_attempt(connection_attempt_data);
}
void
WifiTelemetrySourceWpa::on_network_not_found(const WpaEventArgs<WpaEventNetworkNotFound>& /* args */)
{
if (!trace_station())
return;
auto connection_attempt_data = WifiTelemetryInputStationConnectionAttempt::network_not_found();
complete_connection_attempt(connection_attempt_data);
}
void
WifiTelemetrySourceWpa::complete_dpp_exchange_enrollee(std::shared_ptr<WifiDppExchangeEnrollee>& enrollee)
{
enrollee->stop();
std::vector<uint32_t> chirp_frequencies(enrollee->chirp_frequencies.begin(), enrollee->chirp_frequencies.end());
uint64_t duration_milliseconds = enrollee->duration.has_value()
? static_cast<uint64_t>(enrollee->duration->count())
: 0;
trace_dpp_exchange_enrollee(
m_interface->name.c_str(),
WifiDppRoleToString(enrollee->role),
WifiDppExchangeEnrolleeStateToString(enrollee->state),
duration_milliseconds,
chirp_frequencies.size(),
chirp_frequencies.data(),
WifiDppFailureTypeToString(enrollee->failure_type),
enrollee->failure_details.value_or("").c_str());
m_dpp_exchange.reset();
}
void
WifiTelemetrySourceWpa::complete_dpp_exchange_configurator(std::shared_ptr<WifiDppExchangeConfigurator>& configurator)
{
configurator->stop();
std::string bssid = wifi_80211_mac_to_string(configurator->peer_bssid);
uint64_t duration_milliseconds = configurator->duration.has_value()
? static_cast<uint64_t>(configurator->duration->count())
: 0;
trace_dpp_exchange_configurator(
m_interface->name.c_str(),
WifiDppRoleToString(configurator->role),
WifiDppExchangeConfiguratorStateToString(configurator->state),
duration_milliseconds,
bssid.c_str(),
configurator->frequency,
WifiDppFailureTypeToString(configurator->failure_type),
configurator->failure_details.value_or("").c_str());
m_dpp_exchange.reset();
}
void
WifiTelemetrySourceWpa::on_dpp_chirp_received(const WpaEventArgs<WpaEventDppChirpReceived>& args)
{
if (!trace_dpp_configurator())
return;
const auto& event = args.data();
// configurator doesn't know about this device yet (id == -1), or another exchange in progress.
if (event.id == -1 || is_dpp_exchange_in_progress())
return;
m_dpp_exchange = std::make_shared<WifiDppExchangeConfigurator>(event.id, event.bssid, event.frequency, WifiDppRole::Initiator);
}
void
WifiTelemetrySourceWpa::on_dpp_authentication_init_failure(const WpaEventArgs<WpaEventDppAuthenticationInitFailure>& args)
{
if (!trace_dpp() || !is_dpp_exchange_in_progress())
return;
const auto& event = args.data();
m_dpp_exchange->failure_type = event.failure_type;
m_dpp_exchange->failure_details = event.failure_details;
switch (m_dpp_exchange->device_role) {
case WifiDppDeviceRole::Enrollee: {
auto enrollee = resolve_dpp_exchange<WifiDppExchangeEnrollee>();
enrollee->state = WifiDppExchangeEnrolleeState::Terminated;
complete_dpp_exchange_enrollee(enrollee);
break;
}
case WifiDppDeviceRole::Configurator: {
auto configurator = resolve_dpp_exchange<WifiDppExchangeConfigurator>();
configurator->state = WifiDppExchangeConfiguratorState::Terminated;
complete_dpp_exchange_configurator(configurator);
break;
}
default:
return;
}
}
void
WifiTelemetrySourceWpa::on_dpp_authentication_succeeded(const WpaEventArgs<WpaEventDppAuthenticationSucceeded>& /* args */)
{
if (!trace_dpp() || !is_dpp_exchange_in_progress())
return;
switch (m_dpp_exchange->device_role) {
case WifiDppDeviceRole::Enrollee: {
auto enrollee = resolve_dpp_exchange<WifiDppExchangeEnrollee>();
enrollee->state = WifiDppExchangeEnrolleeState::Authenticated;
break;
}
case WifiDppDeviceRole::Configurator: {
auto configurator = resolve_dpp_exchange<WifiDppExchangeConfigurator>();
configurator->state = WifiDppExchangeConfiguratorState::Authenticated;
break;
}
default:
return;
}
}
void
WifiTelemetrySourceWpa::on_dpp_configuration_received(const WpaEventArgs<WpaEventDppConfigurationReceived>& /* args */)
{
if (!trace_dpp_enrollee() || !is_dpp_exchange_in_progress())
return;
if (m_dpp_exchange->device_role != WifiDppDeviceRole::Enrollee)
return;
auto enrollee = resolve_dpp_exchange<WifiDppExchangeEnrollee>();
enrollee->state = WifiDppExchangeEnrolleeState::Provisioned;
complete_dpp_exchange_enrollee(enrollee);
}
void
WifiTelemetrySourceWpa::on_dpp_configuration_sent(const WpaEventArgs<WpaEventDppConfigurationSent>& /* args */)
{
if (!trace_dpp_configurator() || !is_dpp_exchange_in_progress())
return;
if (m_dpp_exchange->device_role != WifiDppDeviceRole::Configurator)
return;
auto configurator = resolve_dpp_exchange<WifiDppExchangeConfigurator>();
configurator->state = WifiDppExchangeConfiguratorState::Finished;
complete_dpp_exchange_configurator(configurator);
}
void
WifiTelemetrySourceWpa::on_dpp_failure(const WpaEventArgs<WpaEventDppFailure>& args)
{
if (!trace_dpp() || !is_dpp_exchange_in_progress())
return;
const auto& event = args.data();
m_dpp_exchange->failure_type = event.failure_type;
m_dpp_exchange->failure_details = event.failure_details;
switch (m_dpp_exchange->device_role) {
case WifiDppDeviceRole::Enrollee: {
auto enrollee = resolve_dpp_exchange<WifiDppExchangeEnrollee>();
enrollee->state = WifiDppExchangeEnrolleeState::Terminated;
complete_dpp_exchange_enrollee(enrollee);
break;
}
case WifiDppDeviceRole::Configurator: {
auto configurator = resolve_dpp_exchange<WifiDppExchangeConfigurator>();
configurator->state = WifiDppExchangeConfiguratorState::Terminated;
complete_dpp_exchange_configurator(configurator);
break;
}
default:
return;
}
}
void
WifiTelemetrySourceWpa::on_dpp_frame_transmit_status(const WpaEventArgs<WpaEventDppFrameTransmitStatus>& args)
{
if (!trace_dpp_enrollee())
return;
const auto& event = args.data();
bool is_success = (event.status == "SUCCESS");
bool is_broadcast = is_wifi80211_broadcast_address(event.destination_bssid);
if (is_broadcast) { // this indicates a chirp
if (!is_dpp_exchange_in_progress())
m_dpp_exchange = std::make_shared<WifiDppExchangeEnrollee>(WifiDppRole::Responder);
auto enrollee = resolve_dpp_exchange<WifiDppExchangeEnrollee>();
if (is_success)
enrollee->chirp_frequencies.insert(event.frequency);
}
}

Просмотреть файл

@ -0,0 +1,56 @@
#include <numeric>
#include "wifi-telemetry/wifi_telemetry_source_ztpd.hpp"
#include "wifi_telemetry_trace_dpp.hpp"
#define ZTP_DBUS_INTERFACE "com.microsoft.ztp1"
#define ZTP_DBUS_PATH "/com/microsoft/ztp1"
WifiTelemetrySourceZtpd::WifiTelemetrySourceZtpd(const std::optional<WifiInterfaceConfiguration>& interface) :
WifiTelemetrySource(interface, "ztpd"),
ProxyInterfaces(ZTP_DBUS_INTERFACE, ZTP_DBUS_PATH)
{}
WifiTelemetrySourceZtpd::~WifiTelemetrySourceZtpd(void)
{}
int
WifiTelemetrySourceZtpd::activate(const std::shared_ptr<WifiTelemetrySourceActivationArgs> /* args */)
{
registerProxy();
return 0;
}
void
WifiTelemetrySourceZtpd::deactivate(void)
{
unregisterProxy();
}
void
WifiTelemetrySourceZtpd::onPropertiesChanged(const std::string& interfaceName, const std::map<std::string, sdbus::Variant>& changedProperties, const std::vector<std::string>& /* invalidatedProperties */)
{
if (interfaceName != ZTP_DBUS_INTERFACE)
return;
const auto roles_it = changedProperties.find("Roles");
if (roles_it == changedProperties.end())
return;
std::string roles{};
const auto roles_changed = roles_it->second.get<std::vector<std::string>>();
if (!roles_changed.empty()) {
roles = std::accumulate(
/* start */ std::next(std::begin(roles_changed)),
/* end */ std::end(roles_changed),
/* init */ roles_changed.front(),
/* op */ [](std::string current, const std::string& next)
{
return std::move(current) + ',' + next;
});
}
trace_dpp_device_roles_changed(roles.c_str());
}

Просмотреть файл

@ -0,0 +1,39 @@
target_sources(wifi-telemetry
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/wifi_telemetry_input_station_connection_attempt.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_command.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_command_bss.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_command_key_value_pair.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_command_response.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_command_response_parser.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_command_signal_poll.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_command_status.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_controller.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_event.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_event_association_rejected.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_event_authentication_rejected.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_event_connected.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_event_disconnected.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_event_dpp_auth_init_failure.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_event_dpp_auth_success.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_event_dpp_chirp_received.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_event_dpp_conf_received.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_event_dpp_conf_sent.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_event_dpp_failure.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_event_dpp_frame_transmit_status.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_event_handler.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_event_network_not_found.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_event_parser.cxx
${CMAKE_CURRENT_SOURCE_DIR}/wpa_state.cxx
)
target_include_directories(wifi-telemetry
PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
)
target_link_libraries(wifi-telemetry
PRIVATE
Threads::Threads
)

Просмотреть файл

@ -0,0 +1,187 @@
#include <limits>
#include "wifi-telemetry/wifi/wifi_80211_format_mac.hpp"
#include "wifi-telemetry/wpa/wifi_telemetry_input_station_connection_attempt.hpp"
WifiTelemetryInputStationConnectionAttempt::WifiTelemetryInputStationConnectionAttempt(
const WifiConnectionAttemptResult result,
const std::optional<wifi_80211_mac> bssid,
const std::shared_ptr<WpaCommandSignalPollResponse> signal_poll,
const std::shared_ptr<WpaCommandStatusResponse> status,
const WifiStatusCode status_code,
const WifiAuthenticationType authentication_type) :
m_result(result),
m_bssid(wifi_80211_mac_to_string(bssid.value_or(wifi_80211_any_address))),
m_signal_poll(signal_poll ? signal_poll : std::make_shared<WpaCommandSignalPollResponse>(0, 0, 0, 0)),
m_status(status ? status : std::make_shared<WpaCommandStatusResponse>()),
m_status_code(status_code),
m_authentication_type(WifiAuthenticationTypeToString(authentication_type))
{
// sanitize all fields used for telemetry event(s) to defaults
if (!m_status->wifi_generation)
m_status->wifi_generation = 0;
if (!m_status->key_mgmt)
m_status->key_mgmt = "";
if (!m_status->pairwise_cipher)
m_status->pairwise_cipher = "";
if (!m_status->group_cipher)
m_status->group_cipher = "";
if (!m_status->ssid)
m_status->ssid = "";
}
WifiTelemetryInputStationConnectionAttempt
WifiTelemetryInputStationConnectionAttempt::unspecified(void)
{
return {
WifiConnectionAttemptResult::Unspecified,
std::nullopt,
nullptr,
nullptr,
WifiStatusCode::Success,
WifiAuthenticationType::Unknown
};
}
WifiTelemetryInputStationConnectionAttempt
WifiTelemetryInputStationConnectionAttempt::succeeded(const wifi_80211_mac& bssid, const std::shared_ptr<WpaCommandSignalPollResponse> signal_poll, const std::shared_ptr<WpaCommandStatusResponse> status)
{
return {
WifiConnectionAttemptResult::Succeeded,
bssid,
signal_poll,
status,
WifiStatusCode::Success,
WifiAuthenticationType::Unknown
};
}
WifiTelemetryInputStationConnectionAttempt
WifiTelemetryInputStationConnectionAttempt::association_rejected(const std::optional<wifi_80211_mac>& bssid, const WifiStatusCode status_code)
{
return {
WifiConnectionAttemptResult::AssociationRejected,
bssid,
nullptr,
nullptr,
status_code,
WifiAuthenticationType::Unknown
};
}
WifiTelemetryInputStationConnectionAttempt
WifiTelemetryInputStationConnectionAttempt::authentication_rejected(const wifi_80211_mac& /* bssid */, const WifiStatusCode status_code, const WifiAuthenticationType authentication_type)
{
return {
WifiConnectionAttemptResult::AuthenticationRejected,
std::nullopt,
nullptr,
nullptr,
status_code,
authentication_type
};
}
WifiTelemetryInputStationConnectionAttempt
WifiTelemetryInputStationConnectionAttempt::network_not_found(void)
{
return {
WifiConnectionAttemptResult::NetworkNotFound,
std::nullopt,
nullptr,
nullptr,
WifiStatusCode::Success,
WifiAuthenticationType::Unknown
};
}
uint32_t
WifiTelemetryInputStationConnectionAttempt::result(void) const
{
return uint32_t(m_result);
}
const char*
WifiTelemetryInputStationConnectionAttempt::bssid(void) const
{
return m_bssid.c_str();
}
const char*
WifiTelemetryInputStationConnectionAttempt::ssid(void) const
{
return m_status->ssid.value().c_str();
}
int32_t
WifiTelemetryInputStationConnectionAttempt::noise(void) const
{
return m_signal_poll->noise;
}
int32_t
WifiTelemetryInputStationConnectionAttempt::rssi(void) const
{
return m_signal_poll->rssi;
}
int32_t
WifiTelemetryInputStationConnectionAttempt::link_speed(void) const
{
return m_signal_poll->link_speed;
}
uint32_t
WifiTelemetryInputStationConnectionAttempt::frequency(void) const
{
return m_signal_poll->frequency;
}
uint32_t
WifiTelemetryInputStationConnectionAttempt::wifi_generation(void) const
{
return m_status->wifi_generation.value();
}
const char*
WifiTelemetryInputStationConnectionAttempt::key_mgmt(void) const
{
return m_status->key_mgmt.value().c_str();
}
const char*
WifiTelemetryInputStationConnectionAttempt::pairwise_cipher(void) const
{
return m_status->pairwise_cipher.value().c_str();
}
const char*
WifiTelemetryInputStationConnectionAttempt::group_cipher(void) const
{
return m_status->group_cipher.value().c_str();
}
uint16_t
WifiTelemetryInputStationConnectionAttempt::status_code(void) const
{
switch (m_result) {
case WifiConnectionAttemptResult::Succeeded:
case WifiConnectionAttemptResult::AssociationRejected:
case WifiConnectionAttemptResult::AuthenticationRejected:
return uint16_t(m_status_code);
default:
return std::numeric_limits<uint16_t>::max();
}
}
const char*
WifiTelemetryInputStationConnectionAttempt::authentication_type(void) const
{
return m_authentication_type.c_str();
}

Просмотреть файл

@ -0,0 +1,15 @@
#include <iostream>
#include "wifi-telemetry/wpa/wpa_command.hpp"
WpaCommand::WpaCommand(const std::string& name_) :
name(name_)
{}
std::shared_ptr<WpaCommandResponse>
WpaCommand::parse_response(const std::string_view payload) const
{
std::unique_ptr<WpaCommandResponseParser> parser = create_response_parser(payload);
return parser->parse();
}

Просмотреть файл

@ -0,0 +1,57 @@
#include <sstream>
#include "wifi-telemetry/wifi/wifi_80211_format_mac.hpp"
#include "wifi-telemetry/wpa/wpa_command_bss.hpp"
static constexpr char this_command_name[] = "BSS";
WpaCommandBss::WpaCommandBss(std::string bssid_) :
WpaCommand(this_command_name),
bssid(bssid_)
{
std::stringstream ss(name);
ss << " " << bssid;
data = ss.str();
}
std::unique_ptr<WpaCommandResponseParser>
WpaCommandBss::create_response_parser(const std::string_view payload) const
{
return std::make_unique<WpaCommandBssResponseParser>(payload);
}
WpaCommandBssResponseParser::WpaCommandBssResponseParser(const std::string_view payload_) :
WpaCommandResponseParser(this_command_name, payload_, {
{ "id=", WpaValueRequired },
{ "bssid=", WpaValueRequired },
{ "freq=", WpaValueRequired },
{ "beacon_int=", WpaValueRequired },
{ "capabilities=", WpaValueRequired },
{ "qual=", WpaValueRequired },
{ "noise=", WpaValueRequired },
{ "level=", WpaValueRequired },
{ "tsf=", WpaValueRequired },
{ "age=", WpaValueRequired },
{ "ie=", WpaValueRequired },
{ "flags=", WpaValueRequired },
{ "ssid=", WpaValueRequired },
{ "snr=", WpaValueRequired },
{ "est_throughput=", WpaValueRequired },
{ "update_idx=", WpaValueRequired },
{ "beacon_ie=", WpaValueRequired },
})
{}
std::shared_ptr<WpaCommandResponse>
WpaCommandBssResponseParser::parse_payload(void) const
{
return nullptr;
}
WpaCommandBss::WpaCommandBss(const wifi_80211_mac& bssid_) :
WpaCommandBss(wifi_80211_mac_to_string(bssid_))
{}
WpaCommandBssResponse::WpaCommandBssResponse()
{}

Просмотреть файл

@ -0,0 +1,31 @@
#include <string.h>
#include "wifi-telemetry/wpa/wpa_command_key_value_pair.hpp"
WpaCommandKeyValuePair::WpaCommandKeyValuePair(const char* key_, bool is_required_ = WpaValueOptional) :
key(key_),
key_length(strlen(key)),
value(std::nullopt),
is_required(is_required_)
{}
const char*
WpaCommandKeyValuePair::operator()(void) const
{
return value.value();
}
bool
WpaCommandKeyValuePair::resolve(const std::string_view input)
{
value_pos = input.find(key);
if (value_pos != input.npos) {
value_pos += key_length;
value = input.data() + value_pos;
return true;
}
return false;
}

Просмотреть файл

@ -0,0 +1,6 @@
#include "wifi-telemetry/wpa/wpa_command_response.hpp"
WpaCommandResponseGeneric::WpaCommandResponseGeneric(const std::string payload_) :
payload(payload_)
{}

Просмотреть файл

@ -0,0 +1,36 @@
#include <iostream>
#include "wifi-telemetry/wpa/wpa_command_response_parser.hpp"
WpaCommandResponseParser::WpaCommandResponseParser(const std::string& command_name_, const std::string_view payload_, const std::initializer_list<WpaCommandKeyValuePair> properties_) :
command_name(command_name_),
payload(payload_),
properties(properties_)
{}
std::shared_ptr<WpaCommandResponse>
WpaCommandResponseParser::parse(void)
{
return resolve_properties()
? parse_payload()
: nullptr;
}
bool
WpaCommandResponseParser::resolve_properties(void)
{
if (properties_resolved_result.has_value())
return properties_resolved_result.value();
for (auto& property : properties) {
if (!property.resolve(payload) && property.is_required) {
std::cerr << "invalid " << command_name << " response (" << property.key << " not found)" << std::endl;
properties_resolved_result = false;
return false;
}
}
properties_resolved_result = true;
return true;
}

Просмотреть файл

@ -0,0 +1,69 @@
#include <cstdlib>
#include <iostream>
#include <sstream>
#include "wifi-telemetry/wpa/wpa_command_signal_poll.hpp"
static constexpr char this_command_name[] = "SIGNAL_POLL";
WpaCommandSignalPoll::WpaCommandSignalPoll(void) :
WpaCommand(this_command_name)
{
data = name;
}
std::unique_ptr<WpaCommandResponseParser>
WpaCommandSignalPoll::create_response_parser(const std::string_view payload) const
{
return std::make_unique<WpaCommandSignalPollResponseParser>(payload);
}
WpaCommandSignalPollResponseParser::WpaCommandSignalPollResponseParser(const std::string_view payload_) :
WpaCommandResponseParser(this_command_name, payload_, {
{ "RSSI=", WpaValueRequired },
{ "NOISE=", WpaValueRequired },
{ "LINKSPEED=", WpaValueRequired },
{ "FREQUENCY=", WpaValueRequired },
{ "CENTER_FRQ1=", WpaValueOptional },
{ "CENTER_FRQ2=", WpaValueOptional },
{ "WIDTH=", WpaValueOptional },
{ "AVG_RSSI=", WpaValueOptional },
{ "AVG_BEACON_RSSI=", WpaValueOptional },
})
{}
std::shared_ptr<WpaCommandResponse>
WpaCommandSignalPollResponseParser::parse_payload() const
{
int32_t rssi = static_cast<int32_t>(strtol(properties[0](), nullptr, 10));
int32_t noise = static_cast<int32_t>(strtol(properties[1](), nullptr, 10));
int32_t link_speed = static_cast<int32_t>(strtol(properties[2](), nullptr, 10));
uint32_t frequency = static_cast<uint32_t>(strtoul(properties[3](), nullptr, 10));
std::shared_ptr<WpaCommandSignalPollResponse> response = std::make_shared<WpaCommandSignalPollResponse>(noise, rssi, link_speed, frequency);
if (properties[4].value)
response->center_frequency_1 = static_cast<int32_t>(strtol(properties[4](), nullptr, 10));
if (properties[5].value)
response->center_frequency_2 = static_cast<int32_t>(strtol(properties[5](), nullptr, 10));
if (properties[6].value) {
std::size_t value_pos = properties[6].value_pos;
std::size_t value_pos_end = payload.find_first_of('\n', value_pos);
if (value_pos_end != payload.npos)
response->channel_width = payload.substr(value_pos, value_pos_end - value_pos);
}
if (properties[7].value)
response->rssi_average = static_cast<int32_t>(strtol(properties[7](), nullptr, 10));
if (properties[8].value)
response->rssi_average_beacon = static_cast<int32_t>(strtol(properties[8](), nullptr, 10));
return response;
}
WpaCommandSignalPollResponse::WpaCommandSignalPollResponse(int32_t noise_, int32_t rssi_, int32_t link_speed_, uint32_t frequency_) :
noise(noise_),
rssi(rssi_),
link_speed(link_speed_),
frequency(frequency_)
{}

Просмотреть файл

@ -0,0 +1,83 @@
#include <algorithm>
#include "wifi-telemetry/wifi/wifi_80211_format_mac.hpp"
#include "wifi-telemetry/wpa/wpa_command_status.hpp"
static constexpr char this_command_name[] = "STATUS";
WpaCommandStatus::WpaCommandStatus(void) :
WpaCommand(this_command_name)
{
data = name;
}
std::unique_ptr<WpaCommandResponseParser>
WpaCommandStatus::create_response_parser(const std::string_view payload) const
{
return std::make_unique<WpaCommandStatusResponseParser>(payload);
}
WpaCommandStatusResponseParser::WpaCommandStatusResponseParser(const std::string_view payload_) :
WpaCommandResponseParser(this_command_name, payload_, {
{ "wpa_state=", WpaValueRequired },
{ "ssid=", WpaValueOptional },
{ "bssid=", WpaValueOptional },
{ "pairwise_cipher=", WpaValueOptional },
{ "group_cipher=", WpaValueOptional },
{ "key_mgmt=", WpaValueOptional },
{ "wifi_generation=", WpaValueOptional },
{ "freq=", WpaValueOptional },
})
{}
std::shared_ptr<WpaCommandResponse>
WpaCommandStatusResponseParser::parse_payload(void) const
{
std::string state = properties[0]();
state.erase(state.find_first_of('\n'));
auto response = std::make_shared<WpaCommandStatusResponse>(wpa_state_from_string(state.c_str()));
if (properties[1].value) {
std::string ssid = properties[1]();
ssid.erase(ssid.find_first_of('\n'));
response->ssid = std::move(ssid);
}
if (properties[2].value) {
std::string bssid = properties[2]();
bssid.erase(bssid.find_first_of('\n'));
response->bssid = wifi_80211_mac_from_string(bssid);
}
if (properties[3].value) {
std::string pairwise_cipher = properties[3]();
pairwise_cipher.erase(pairwise_cipher.find_first_of('\n'));
response->pairwise_cipher = std::move(pairwise_cipher);
}
if (properties[4].value) {
std::string group_cipher = properties[4]();
group_cipher.erase(group_cipher.find_first_of('\n'));
response->group_cipher = std::move(group_cipher);
}
if (properties[5].value) {
std::string key_mgmt = properties[5]();
key_mgmt.erase(key_mgmt.find_first_of('\n'));
response->key_mgmt = std::move(key_mgmt);
}
if (properties[6].value)
response->wifi_generation = static_cast<uint32_t>(strtoul(properties[6](), nullptr, 10));
if (properties[7].value)
response->frequency = static_cast<uint32_t>(strtoul(properties[7](), nullptr, 10));
return response;
}
WpaCommandStatusResponse::WpaCommandStatusResponse(WpaState state_) :
state(state_)
{}

Просмотреть файл

@ -0,0 +1,312 @@
#include <array>
#include <cerrno>
#include <filesystem>
#include <iostream>
#include <sys/epoll.h>
#include <sys/eventfd.h>
#include <sys/types.h>
#include <unistd.h>
#include "wifi-telemetry/wpa/wpa_controller.hpp"
#include "wpa_event_parser.hpp"
WpaController::WpaController(const std::string_view interface, WpaType type) :
WpaController(interface, type, WpaController::default_control_socket_path(type))
{
}
WpaController::WpaController(const std::string_view interface, WpaType type, const std::string_view control_socket_path) :
m_type(type),
m_interface(interface),
m_ctrl_socket_path(control_socket_path)
{
m_ctrl_event_thread = std::thread([this](void)
{
process_wpa_events();
});
}
WpaController::~WpaController(void)
{
m_terminate_pending = true;
if (m_ctrl_event_fd_stop != -1) {
uint64_t value = 1;
ssize_t num_written = write(m_ctrl_event_fd_stop, &value, sizeof value);
if (num_written != sizeof value) {
int ret = (num_written < 0) ? errno : -ERANGE;
std::cerr << "failed to write exit signal descriptor value (" << ret << ")" << std::endl;
}
}
auto lock_exclusive = std::scoped_lock(m_ctrl_command_gate);
if (m_ctrl_command) {
wpa_ctrl_close(m_ctrl_command);
m_ctrl_command = nullptr;
}
m_ctrl_event_thread.join();
}
/**
* @brief Process a pending wpa event.
*/
void
WpaController::process_wpa_event_next(void)
{
auto timestamp = std::chrono::system_clock::now();
char buffer[WpaController::c_wpa_event_size_max];
size_t buffer_length = sizeof buffer - 1;
int ret = wpa_ctrl_recv(m_ctrl_event, buffer, &buffer_length);
if (ret < 0) {
std::cerr << "failed to receive message from wpa control socket" << std::endl;
return;
}
buffer[buffer_length] = '\0';
std::shared_ptr<WpaEvent> event = WpaEventParser::parse(buffer);
if (!event)
return;
// Make a copy of the event subscribers to minimize the time holding the
// lock. This is safe since the validity of each subscriber will later be
// attempted to be promoted to a full shared_ptr prior to using it.
decltype(m_event_subscribers) event_subscribers;
{
auto lock = std::scoped_lock(m_event_subscribers_gate);
event_subscribers = m_event_subscribers;
}
for (const auto& [token, handler_weak] : event_subscribers) {
std::shared_ptr<WpaEventHandler> handler = handler_weak.lock();
if (!handler)
continue;
switch (event->type) {
case WpaEventType::Connected:
handler->on_connected({ timestamp, std::dynamic_pointer_cast<WpaEventConnected>(event) });
break;
case WpaEventType::Disconnected:
handler->on_disconnected({ timestamp, std::dynamic_pointer_cast<WpaEventDisconnected>(event) });
break;
case WpaEventType::AssociationRejected:
handler->on_association_rejected({ timestamp, std::dynamic_pointer_cast<WpaEventAssociationRejected>(event) });
break;
case WpaEventType::AuthenticationRejected:
handler->on_authentication_rejected({ timestamp, std::dynamic_pointer_cast<WpaEventAuthenticationRejected>(event) });
break;
case WpaEventType::NetworkNotFound:
handler->on_network_not_found({ timestamp, std::dynamic_pointer_cast<WpaEventNetworkNotFound>(event) });
break;
case WpaEventType::DppAuthenticationInitFailure:
handler->on_dpp_authentication_init_failure({ timestamp, std::dynamic_pointer_cast<WpaEventDppAuthenticationInitFailure>(event) });
break;
case WpaEventType::DppAuthenticationSucceeded:
handler->on_dpp_authentication_succeeded({ timestamp, std::dynamic_pointer_cast<WpaEventDppAuthenticationSucceeded>(event) });
break;
case WpaEventType::DppConfigurationReceived:
handler->on_dpp_configuration_received({ timestamp, std::dynamic_pointer_cast<WpaEventDppConfigurationReceived>(event) });
break;
case WpaEventType::DppConfigurationSent:
handler->on_dpp_configuration_sent({ timestamp, std::dynamic_pointer_cast<WpaEventDppConfigurationSent>(event) });
break;
case WpaEventType::DppFailure:
handler->on_dpp_failure({ timestamp, std::dynamic_pointer_cast<WpaEventDppFailure>(event) });
break;
case WpaEventType::DppChirpReceived:
handler->on_dpp_chirp_received({ timestamp, std::dynamic_pointer_cast<WpaEventDppChirpReceived>(event) });
break;
case WpaEventType::DppFrameTransmitStatus:
handler->on_dpp_frame_transmit_status({ timestamp, std::dynamic_pointer_cast<WpaEventDppFrameTransmitStatus>(event) });
break;
}
}
}
void
WpaController::process_wpa_events(void)
{
static constexpr int epoll_events_max = 2;
int ret;
int fd_efd = -1;
int fd_wpa = -1;
bool terminate = false;
struct wpa_ctrl* ctrl = nullptr;
struct epoll_event events[epoll_events_max] = {};
struct epoll_event* event_efd = &events[0];
struct epoll_event* event_wpa = &events[1];
const std::filesystem::path path = m_ctrl_socket_path / m_interface;
int fd_epoll = epoll_create1(0);
if (fd_epoll < 0) {
ret = errno;
std::cerr << "failed to create epoll instance for wpa event listener (" << ret << ")" << std::endl;
return;
}
// configure eventfd descriptor for thread stop signaling.
fd_efd = eventfd(0, 0);
if (fd_efd == -1) {
ret = errno;
std::cerr << "failed to create stop event fd (" << ret << ")" << std::endl;
goto cleanup;
}
event_efd->events = EPOLLIN;
event_efd->data.fd = fd_efd;
ret = epoll_ctl(fd_epoll, EPOLL_CTL_ADD, fd_efd, event_efd);
if (ret < 0) {
ret = errno;
std::cerr << "failed to register epoll handler for event stop signaling (" << ret << ")" << std::endl;
goto cleanup;
}
// configure control socket descriptor for wpa event signaling.
ctrl = wpa_ctrl_open(path.c_str());
if (!ctrl) {
std::cerr << "failed to open wpa control socket " << path << std::endl;
goto cleanup;
}
fd_wpa = wpa_ctrl_get_fd(ctrl);
event_wpa->events = EPOLLIN;
event_wpa->data.fd = fd_wpa;
ret = epoll_ctl(fd_epoll, EPOLL_CTL_ADD, fd_wpa, event_wpa);
if (ret < 0) {
ret = errno;
std::cerr << "failed to register epoll handler for wpa event listener (" << ret << ")" << std::endl;
goto cleanup;
}
// attach to wpa event stream
ret = wpa_ctrl_attach(ctrl);
if (ret < 0) {
std::cerr << "failed to register event monitor on wpa control socket (" << ret << ")" << std::endl;
goto cleanup;
}
m_ctrl_event = ctrl;
m_ctrl_event_fd_stop = fd_efd;
while (!m_terminate_pending && !terminate) {
// wait for at least one event fd to be signaled
int num_events = epoll_wait(fd_epoll, events, epoll_events_max, -1);
if (num_events < 0) {
ret = errno;
std::cerr << "failed to wait on epoll event (" << ret << ")" << std::endl;
continue;
} else if (num_events == 0) {
continue;
}
// determine which fd(s) were signaled and handle them.
for (int i = 0; i < epoll_events_max; i++) {
if (events[i].data.fd == fd_efd) {
uint64_t value;
ssize_t num_read = read(fd_efd, &value, sizeof value);
if (num_read != sizeof value) {
ret = errno;
std::cerr << "failed to read exit signal descriptor (" << ret << ")" << std::endl;
continue;
} else if (value > 0) {
terminate = true;
}
} else if (events[i].data.fd == fd_wpa) {
while (wpa_ctrl_pending(ctrl) > 0)
process_wpa_event_next();
}
}
}
cleanup:
if (ctrl) {
wpa_ctrl_detach(ctrl);
wpa_ctrl_close(ctrl);
}
if (fd_efd != -1)
close(fd_efd);
close(fd_epoll);
m_ctrl_event_fd_stop = -1;
m_ctrl_event = nullptr;
}
WpaEventToken
WpaController::register_for_events(std::weak_ptr<WpaEventHandler> handler)
{
auto lock = std::scoped_lock(m_event_subscribers_gate);
WpaEventToken token = m_event_token_next++;
m_event_subscribers[token] = handler;
return token;
}
void
WpaController::unregister_for_events(WpaEventToken token)
{
auto lock = std::scoped_lock(m_event_subscribers_gate);
m_event_subscribers.erase(token);
}
struct wpa_ctrl*
WpaController::get_command_control_socket(void)
{
const std::filesystem::path path = m_ctrl_socket_path / m_interface;
// Check if the socket is already available.
{
auto lock_shared = std::shared_lock(m_ctrl_command_gate);
if (m_ctrl_command)
return m_ctrl_command;
}
// Check if socket was updated between releasing shared lock and acquiring exclusive lock.
auto lock_exclusive = std::scoped_lock(m_ctrl_command_gate);
if (m_ctrl_command)
return m_ctrl_command;
struct wpa_ctrl* ctrl = wpa_ctrl_open(path.c_str());
if (!ctrl) {
std::cerr << "failed to open wpa control socket " << path << std::endl;
return nullptr;
}
m_ctrl_command = ctrl;
return m_ctrl_command;
}
std::shared_ptr<WpaCommandResponse>
WpaController::send_command(const WpaCommand& command)
{
struct wpa_ctrl* ctrl = get_command_control_socket();
if (!ctrl) {
std::cerr << "failed to obtain wpa command control socket" << std::endl;
return nullptr;
}
std::array<char, c_wpa_event_size_max> reply;
std::size_t reply_length = reply.size();
int ret = wpa_ctrl_request(ctrl, command.data.c_str(), command.data.length(), reply.data(), &reply_length, nullptr);
switch (ret) {
case 0:
return command.parse_response(std::string_view(reply.data(), reply_length));
case -2:
std::cerr << "failed to send/receive wpa command " << command.name << "(timeout)" << std::endl;
return nullptr;
case -1:
std::cerr << "failed to send/receive wpa command " << command.name << std::endl;
return nullptr;
default:
std::cerr << "failed to send/receive wpa command " << command.name << "(unspecified error " << ret << ")" << std::endl;
return nullptr;
}
}

Просмотреть файл

@ -0,0 +1,9 @@
#include <chrono>
#include <iostream>
#include "wifi-telemetry/wpa/wpa_event.hpp"
WpaEvent::WpaEvent(WpaEventType type_) :
type(type_)
{}

Просмотреть файл

@ -0,0 +1,15 @@
#include "wifi-telemetry/wpa/wpa_event_association_rejected.hpp"
WpaEventAssociationRejected::WpaEventAssociationRejected(WifiStatusCode status_code_) :
WpaEvent(WpaEventType::AssociationRejected),
status_code(status_code_)
{
}
WpaEventAssociationRejected::WpaEventAssociationRejected(WifiStatusCode status_code_, const wifi_80211_mac& bssid_) :
WpaEvent(WpaEventType::AssociationRejected),
status_code(status_code_),
bssid(bssid_)
{
}

Просмотреть файл

@ -0,0 +1,10 @@
#include "wifi-telemetry/wpa/wpa_event_authentication_rejected.hpp"
WpaEventAuthenticationRejected::WpaEventAuthenticationRejected(const wifi_80211_mac& bssid_, WifiStatusCode status_code_, WifiAuthenticationType authentication_type_) :
WpaEvent(WpaEventType::AuthenticationRejected),
bssid(bssid_),
status_code(status_code_),
authentication_type(authentication_type_)
{
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше