about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--.clang-format8
-rw-r--r--.github/workflows/x86_64.yml27
-rw-r--r--.gitignore23
-rw-r--r--AUTHORS10
-rw-r--r--CMakeLists.txt51
-rw-r--r--COPYING15
-rw-r--r--LICENSE201
-rw-r--r--README.md88
-rw-r--r--benchmark/Makefile9
-rw-r--r--benchmark/benchmark_beacon.c37
-rw-r--r--examples/generate_beacon/README.md19
-rw-r--r--examples/generate_beacon/generate_beacon.c80
-rw-r--r--examples/generate_rtscts/README.md23
-rw-r--r--examples/generate_rtscts/generate_rtscts.c78
-rw-r--r--examples/parse_beacon/README.md65
-rw-r--r--examples/parse_beacon/parse_beacon.c158
-rw-r--r--examples/parse_eapol/README.md74
-rw-r--r--examples/parse_eapol/parse_eapol.c140
-rwxr-xr-xscripts/generate_entry_header.sh31
-rw-r--r--src/libwifi.h75
-rw-r--r--src/libwifi/core/core.c46
-rw-r--r--src/libwifi/core/core.h53
-rw-r--r--src/libwifi/core/frame/control/cts.h35
-rw-r--r--src/libwifi/core/frame/control/rts.h38
-rw-r--r--src/libwifi/core/frame/crc.c63
-rw-r--r--src/libwifi/core/frame/crc.h49
-rw-r--r--src/libwifi/core/frame/data/data.h32
-rw-r--r--src/libwifi/core/frame/frame.c145
-rw-r--r--src/libwifi/core/frame/frame.h334
-rw-r--r--src/libwifi/core/frame/management/action.h93
-rw-r--r--src/libwifi/core/frame/management/assoc_request.h51
-rw-r--r--src/libwifi/core/frame/management/assoc_response.h54
-rw-r--r--src/libwifi/core/frame/management/atim.h33
-rw-r--r--src/libwifi/core/frame/management/authentication.h54
-rw-r--r--src/libwifi/core/frame/management/beacon.h54
-rw-r--r--src/libwifi/core/frame/management/common.h101
-rw-r--r--src/libwifi/core/frame/management/deauthentication.h55
-rw-r--r--src/libwifi/core/frame/management/disassociation.h55
-rw-r--r--src/libwifi/core/frame/management/probe_request.h38
-rw-r--r--src/libwifi/core/frame/management/probe_response.h54
-rw-r--r--src/libwifi/core/frame/management/reassoc_request.h54
-rw-r--r--src/libwifi/core/frame/management/reassoc_response.h54
-rw-r--r--src/libwifi/core/frame/management/timing_ad.h82
-rw-r--r--src/libwifi/core/frame/tag.c131
-rw-r--r--src/libwifi/core/frame/tag.h306
-rw-r--r--src/libwifi/core/frame/tag_iterator.c55
-rw-r--r--src/libwifi/core/frame/tag_iterator.h53
-rw-r--r--src/libwifi/core/misc/byteswap.h31
-rw-r--r--src/libwifi/core/misc/epoch.c23
-rw-r--r--src/libwifi/core/misc/epoch.h26
-rw-r--r--src/libwifi/core/misc/llc.h33
-rw-r--r--src/libwifi/core/misc/radiotap.h83
-rw-r--r--src/libwifi/core/misc/security.h289
-rw-r--r--src/libwifi/core/misc/types.h218
-rw-r--r--src/libwifi/core/radiotap/COPYING14
-rw-r--r--src/libwifi/core/radiotap/platform.h81
-rw-r--r--src/libwifi/core/radiotap/radiotap.c469
-rw-r--r--src/libwifi/core/radiotap/radiotap.h221
-rw-r--r--src/libwifi/core/radiotap/radiotap_iter.h101
-rw-r--r--src/libwifi/gen/control/cts.c30
-rw-r--r--src/libwifi/gen/control/cts.h30
-rw-r--r--src/libwifi/gen/control/rts.c32
-rw-r--r--src/libwifi/gen/control/rts.h32
-rw-r--r--src/libwifi/gen/management/action.c110
-rw-r--r--src/libwifi/gen/management/action.h80
-rw-r--r--src/libwifi/gen/management/assoc_request.c85
-rw-r--r--src/libwifi/gen/management/assoc_request.h39
-rw-r--r--src/libwifi/gen/management/assoc_response.c106
-rw-r--r--src/libwifi/gen/management/assoc_response.h69
-rw-r--r--src/libwifi/gen/management/atim.c35
-rw-r--r--src/libwifi/gen/management/atim.h24
-rw-r--r--src/libwifi/gen/management/authentication.c81
-rw-r--r--src/libwifi/gen/management/authentication.h64
-rw-r--r--src/libwifi/gen/management/beacon.c117
-rw-r--r--src/libwifi/gen/management/beacon.h78
-rw-r--r--src/libwifi/gen/management/common.h54
-rw-r--r--src/libwifi/gen/management/deauthentication.c82
-rw-r--r--src/libwifi/gen/management/deauthentication.h63
-rw-r--r--src/libwifi/gen/management/disassociation.c80
-rw-r--r--src/libwifi/gen/management/disassociation.h63
-rw-r--r--src/libwifi/gen/management/probe_request.c76
-rw-r--r--src/libwifi/gen/management/probe_request.h64
-rw-r--r--src/libwifi/gen/management/probe_response.c118
-rw-r--r--src/libwifi/gen/management/probe_response.h78
-rw-r--r--src/libwifi/gen/management/reassoc_request.c87
-rw-r--r--src/libwifi/gen/management/reassoc_request.h30
-rw-r--r--src/libwifi/gen/management/reassoc_response.c108
-rw-r--r--src/libwifi/gen/management/reassoc_response.h70
-rw-r--r--src/libwifi/gen/management/timing_ad.c111
-rw-r--r--src/libwifi/gen/management/timing_ad.h32
-rw-r--r--src/libwifi/gen/misc/radiotap.c123
-rw-r--r--src/libwifi/gen/misc/radiotap.h31
-rw-r--r--src/libwifi/parse/data/data.c48
-rw-r--r--src/libwifi/parse/data/data.h26
-rw-r--r--src/libwifi/parse/data/eapol.c190
-rw-r--r--src/libwifi/parse/data/eapol.h91
-rw-r--r--src/libwifi/parse/management/assoc_request.c79
-rw-r--r--src/libwifi/parse/management/assoc_request.h32
-rw-r--r--src/libwifi/parse/management/assoc_response.c92
-rw-r--r--src/libwifi/parse/management/assoc_response.h35
-rw-r--r--src/libwifi/parse/management/beacon.c91
-rw-r--r--src/libwifi/parse/management/beacon.h35
-rw-r--r--src/libwifi/parse/management/common.c192
-rw-r--r--src/libwifi/parse/management/common.h70
-rw-r--r--src/libwifi/parse/management/deauthentication.c74
-rw-r--r--src/libwifi/parse/management/deauthentication.h25
-rw-r--r--src/libwifi/parse/management/disassociation.c72
-rw-r--r--src/libwifi/parse/management/disassociation.h25
-rw-r--r--src/libwifi/parse/management/probe_request.c72
-rw-r--r--src/libwifi/parse/management/probe_request.h32
-rw-r--r--src/libwifi/parse/management/probe_response.c88
-rw-r--r--src/libwifi/parse/management/probe_response.h35
-rw-r--r--src/libwifi/parse/management/reassoc_request.c79
-rw-r--r--src/libwifi/parse/management/reassoc_request.h32
-rw-r--r--src/libwifi/parse/management/reassoc_response.c92
-rw-r--r--src/libwifi/parse/management/reassoc_response.h35
-rw-r--r--src/libwifi/parse/misc/radiotap.c126
-rw-r--r--src/libwifi/parse/misc/radiotap.h39
-rw-r--r--src/libwifi/parse/misc/security.c685
-rw-r--r--src/libwifi/parse/misc/security.h124
-rw-r--r--test/CMakeLists.txt16
-rw-r--r--test/pcaps/assoc_req.pcapbin0 -> 4374 bytes
-rw-r--r--test/pcaps/assoc_resp.pcapbin0 -> 3924 bytes
-rw-r--r--test/pcaps/auth.pcapbin0 -> 6524 bytes
-rw-r--r--test/pcaps/beacons_with_221.pcapbin0 -> 7674 bytes
-rw-r--r--test/pcaps/deauth.pcapbin0 -> 3074 bytes
-rw-r--r--test/pcaps/deauth_with_221.pcapbin0 -> 5024 bytes
-rw-r--r--test/pcaps/disassoc.pcapbin0 -> 3074 bytes
-rw-r--r--test/pcaps/probe_req.pcapbin0 -> 4074 bytes
-rw-r--r--test/pcaps/probe_resp_with_221.pcapbin0 -> 7874 bytes
-rw-r--r--test/pcaps/reassoc_req.pcapbin0 -> 4674 bytes
-rw-r--r--test/pcaps/reassoc_resp.pcapbin0 -> 3924 bytes
-rw-r--r--test/src/.clang-format8
-rw-r--r--test/src/helpers.c31
-rw-r--r--test/src/helpers.h60
-rw-r--r--test/src/test_generation.c924
-rw-r--r--test/src/test_misc.c30
-rw-r--r--test/src/test_parsing.c613
138 files changed, 11553 insertions, 0 deletions
diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..cce8123 --- /dev/null +++ b/.clang-format
@@ -0,0 +1,8 @@
1---
2BasedOnStyle: LLVM
3IndentWidth: '4'
4SpaceAfterCStyleCast: 'true'
5ColumnLimit: 110
6AllowShortFunctionsOnASingleLine: None
7IndentCaseLabels: 'true'
8...
diff --git a/.github/workflows/x86_64.yml b/.github/workflows/x86_64.yml new file mode 100644 index 0000000..844a109 --- /dev/null +++ b/.github/workflows/x86_64.yml
@@ -0,0 +1,27 @@
1name: libwifi (64-Bit)
2
3on: [push]
4
5env:
6 # Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
7 BUILD_TYPE: Release
8
9jobs:
10 build:
11 runs-on: ubuntu-latest
12
13 steps:
14 - uses: actions/checkout@v2
15
16 - name: Create Build Environment
17 run: cmake -E make_directory ${{github.workspace}}/build
18
19 - name: Configure CMake
20 shell: bash
21 working-directory: ${{github.workspace}}/build
22 run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE
23
24 - name: Build X86_64
25 working-directory: ${{github.workspace}}/build
26 shell: bash
27 run: cmake --build . --config $BUILD_TYPE
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dbbe0da --- /dev/null +++ b/.gitignore
@@ -0,0 +1,23 @@
1# Binaries
2*.a
3*.o
4*.so*
5
6# Build
7CMakeLists.txt.user
8CMakeCache.txt
9CMakeFiles
10CMakeScripts
11Testing
12Makefile
13cmake_install.cmake
14install_manifest.txt
15compile_commands.json
16CTestTestfile.cmake
17_deps
18CMakeUserPresets.json
19*-prefix/
20
21# Output
22build/
23tests/build/
diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..8c7299c --- /dev/null +++ b/AUTHORS
@@ -0,0 +1,10 @@
1# This is the list of libwifi's significant contributors.
2#
3# This does not necessarily list everyone who has contributed code,
4# especially since many employees of one corporation may be contributing.
5# To see the full list of contributors, see the revision history in
6# source control.
7Marc Egerton
8Sebastian Kinne
9Henry Pitcairn
10Hak5 LLC
diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..3a94d82 --- /dev/null +++ b/CMakeLists.txt
@@ -0,0 +1,51 @@
1cmake_minimum_required(VERSION 3.18)
2
3project(wifi DESCRIPTION "802.11 Parsing / Generation library" VERSION 0.1)
4
5execute_process(COMMAND git rev-parse --abbrev-ref HEAD OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE GITBRANCH)
6execute_process(COMMAND git log -1 --pretty=format:%h OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE GITHASH)
7execute_process(COMMAND date OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE BUILDTIME)
8set(LIBWIFI_VERSION "0.0.1")
9
10message(" ")
11message(" _ _ _ _ __ _ ")
12message("| |(_)| | (_) / _|(_) ")
13message("| | _ | |__ __ __ _ | |_ _ ")
14message("| || || '_ \\ \\ \\ /\\ / /| || _|| | ")
15message("| || || |_| | \\ V V / | || | | | ")
16message("|_||_||_.__/ \\_/\\_/ |_||_| |_| ")
17message("-----------------------------------")
18message("802.11 Parsing / Generation Library")
19message("Version: ${LIBWIFI_VERSION}, Git: ${GITBRANCH} (${GITHASH}), Time: ${BUILDTIME}")
20message(" ")
21
22file(GLOB_RECURSE libwifi_src
23 "src/libwifi/*.h"
24 "src/libwifi/*.c"
25)
26
27set(CMAKE_C_COMPILER "/usr/bin/clang")
28set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu17")
29set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra")
30set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pedantic -Wno-language-extension-token")
31set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wmissing-prototypes -Wstrict-prototypes")
32set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fstack-protector-strong")
33
34if (CMAKE_BUILD_TYPE STREQUAL "Debug")
35 message("Building as Debug")
36 set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ggdb -O0")
37endif(CMAKE_BUILD_TYPE STREQUAL "Debug")
38
39add_library(wifi SHARED ${libwifi_src})
40
41set_target_properties(wifi PROPERTIES LINKER_LANGUAGE C)
42set_target_properties(wifi PROPERTIES VERSION ${LIBWIFI_VERSION})
43set_target_properties(wifi PROPERTIES SOVERSION 0)
44set_target_properties(wifi PROPERTIES PUBLIC_HEADER src/libwifi.h)
45
46install(DIRECTORY src/libwifi/core/ DESTINATION /usr/include/libwifi/core FILES_MATCHING PATTERN "*.h")
47install(DIRECTORY src/libwifi/parse/ DESTINATION /usr/include/libwifi/parse FILES_MATCHING PATTERN "*.h")
48install(DIRECTORY src/libwifi/gen/ DESTINATION /usr/include/libwifi/gen FILES_MATCHING PATTERN "*.h")
49install(TARGETS wifi LIBRARY DESTINATION /usr/lib PUBLIC_HEADER DESTINATION /usr/include)
50
51add_custom_target(uninstall COMMAND rm -rf /usr/include/libwifi; rm -rf /usr/include/libwifi.h)
diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..1b7fb0a --- /dev/null +++ b/COPYING
@@ -0,0 +1,15 @@
1/* Copyright 2021 The libwifi Authors
2*
3* Licensed under the Apache License, Version 2.0 (the "License");
4* you may not use this file except in compliance with the License.
5* You may obtain a copy of the License at
6*
7* http://www.apache.org/licenses/LICENSE-2.0
8*
9* Unless required by applicable law or agreed to in writing, software
10* distributed under the License is distributed on an "AS IS" BASIS,
11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12* See the License for the specific language governing permissions and
13* limitations under the License.
14*/
15
diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..27bc874 --- /dev/null +++ b/LICENSE
@@ -0,0 +1,201 @@
1 Apache License
2 Version 2.0, January 2004
3 http://www.apache.org/licenses/
4
5 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
7 1. Definitions.
8
9 "License" shall mean the terms and conditions for use, reproduction,
10 and distribution as defined by Sections 1 through 9 of this document.
11
12 "Licensor" shall mean the copyright owner or entity authorized by
13 the copyright owner that is granting the License.
14
15 "Legal Entity" shall mean the union of the acting entity and all
16 other entities that control, are controlled by, or are under common
17 control with that entity. For the purposes of this definition,
18 "control" means (i) the power, direct or indirect, to cause the
19 direction or management of such entity, whether by contract or
20 otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 outstanding shares, or (iii) beneficial ownership of such entity.
22
23 "You" (or "Your") shall mean an individual or Legal Entity
24 exercising permissions granted by this License.
25
26 "Source" form shall mean the preferred form for making modifications,
27 including but not limited to software source code, documentation
28 source, and configuration files.
29
30 "Object" form shall mean any form resulting from mechanical
31 transformation or translation of a Source form, including but
32 not limited to compiled object code, generated documentation,
33 and conversions to other media types.
34
35 "Work" shall mean the work of authorship, whether in Source or
36 Object form, made available under the License, as indicated by a
37 copyright notice that is included in or attached to the work
38 (an example is provided in the Appendix below).
39
40 "Derivative Works" shall mean any work, whether in Source or Object
41 form, that is based on (or derived from) the Work and for which the
42 editorial revisions, annotations, elaborations, or other modifications
43 represent, as a whole, an original work of authorship. For the purposes
44 of this License, Derivative Works shall not include works that remain
45 separable from, or merely link (or bind by name) to the interfaces of,
46 the Work and Derivative Works thereof.
47
48 "Contribution" shall mean any work of authorship, including
49 the original version of the Work and any modifications or additions
50 to that Work or Derivative Works thereof, that is intentionally
51 submitted to Licensor for inclusion in the Work by the copyright owner
52 or by an individual or Legal Entity authorized to submit on behalf of
53 the copyright owner. For the purposes of this definition, "submitted"
54 means any form of electronic, verbal, or written communication sent
55 to the Licensor or its representatives, including but not limited to
56 communication on electronic mailing lists, source code control systems,
57 and issue tracking systems that are managed by, or on behalf of, the
58 Licensor for the purpose of discussing and improving the Work, but
59 excluding communication that is conspicuously marked or otherwise
60 designated in writing by the copyright owner as "Not a Contribution."
61
62 "Contributor" shall mean Licensor and any individual or Legal Entity
63 on behalf of whom a Contribution has been received by Licensor and
64 subsequently incorporated within the Work.
65
66 2. Grant of Copyright License. Subject to the terms and conditions of
67 this License, each Contributor hereby grants to You a perpetual,
68 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 copyright license to reproduce, prepare Derivative Works of,
70 publicly display, publicly perform, sublicense, and distribute the
71 Work and such Derivative Works in Source or Object form.
72
73 3. Grant of Patent License. Subject to the terms and conditions of
74 this License, each Contributor hereby grants to You a perpetual,
75 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 (except as stated in this section) patent license to make, have made,
77 use, offer to sell, sell, import, and otherwise transfer the Work,
78 where such license applies only to those patent claims licensable
79 by such Contributor that are necessarily infringed by their
80 Contribution(s) alone or by combination of their Contribution(s)
81 with the Work to which such Contribution(s) was submitted. If You
82 institute patent litigation against any entity (including a
83 cross-claim or counterclaim in a lawsuit) alleging that the Work
84 or a Contribution incorporated within the Work constitutes direct
85 or contributory patent infringement, then any patent licenses
86 granted to You under this License for that Work shall terminate
87 as of the date such litigation is filed.
88
89 4. Redistribution. You may reproduce and distribute copies of the
90 Work or Derivative Works thereof in any medium, with or without
91 modifications, and in Source or Object form, provided that You
92 meet the following conditions:
93
94 (a) You must give any other recipients of the Work or
95 Derivative Works a copy of this License; and
96
97 (b) You must cause any modified files to carry prominent notices
98 stating that You changed the files; and
99
100 (c) You must retain, in the Source form of any Derivative Works
101 that You distribute, all copyright, patent, trademark, and
102 attribution notices from the Source form of the Work,
103 excluding those notices that do not pertain to any part of
104 the Derivative Works; and
105
106 (d) If the Work includes a "NOTICE" text file as part of its
107 distribution, then any Derivative Works that You distribute must
108 include a readable copy of the attribution notices contained
109 within such NOTICE file, excluding those notices that do not
110 pertain to any part of the Derivative Works, in at least one
111 of the following places: within a NOTICE text file distributed
112 as part of the Derivative Works; within the Source form or
113 documentation, if provided along with the Derivative Works; or,
114 within a display generated by the Derivative Works, if and
115 wherever such third-party notices normally appear. The contents
116 of the NOTICE file are for informational purposes only and
117 do not modify the License. You may add Your own attribution
118 notices within Derivative Works that You distribute, alongside
119 or as an addendum to the NOTICE text from the Work, provided
120 that such additional attribution notices cannot be construed
121 as modifying the License.
122
123 You may add Your own copyright statement to Your modifications and
124 may provide additional or different license terms and conditions
125 for use, reproduction, or distribution of Your modifications, or
126 for any such Derivative Works as a whole, provided Your use,
127 reproduction, and distribution of the Work otherwise complies with
128 the conditions stated in this License.
129
130 5. Submission of Contributions. Unless You explicitly state otherwise,
131 any Contribution intentionally submitted for inclusion in the Work
132 by You to the Licensor shall be under the terms and conditions of
133 this License, without any additional terms or conditions.
134 Notwithstanding the above, nothing herein shall supersede or modify
135 the terms of any separate license agreement you may have executed
136 with Licensor regarding such Contributions.
137
138 6. Trademarks. This License does not grant permission to use the trade
139 names, trademarks, service marks, or product names of the Licensor,
140 except as required for reasonable and customary use in describing the
141 origin of the Work and reproducing the content of the NOTICE file.
142
143 7. Disclaimer of Warranty. Unless required by applicable law or
144 agreed to in writing, Licensor provides the Work (and each
145 Contributor provides its Contributions) on an "AS IS" BASIS,
146 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 implied, including, without limitation, any warranties or conditions
148 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 PARTICULAR PURPOSE. You are solely responsible for determining the
150 appropriateness of using or redistributing the Work and assume any
151 risks associated with Your exercise of permissions under this License.
152
153 8. Limitation of Liability. In no event and under no legal theory,
154 whether in tort (including negligence), contract, or otherwise,
155 unless required by applicable law (such as deliberate and grossly
156 negligent acts) or agreed to in writing, shall any Contributor be
157 liable to You for damages, including any direct, indirect, special,
158 incidental, or consequential damages of any character arising as a
159 result of this License or out of the use or inability to use the
160 Work (including but not limited to damages for loss of goodwill,
161 work stoppage, computer failure or malfunction, or any and all
162 other commercial damages or losses), even if such Contributor
163 has been advised of the possibility of such damages.
164
165 9. Accepting Warranty or Additional Liability. While redistributing
166 the Work or Derivative Works thereof, You may choose to offer,
167 and charge a fee for, acceptance of support, warranty, indemnity,
168 or other liability obligations and/or rights consistent with this
169 License. However, in accepting such obligations, You may act only
170 on Your own behalf and on Your sole responsibility, not on behalf
171 of any other Contributor, and only if You agree to indemnify,
172 defend, and hold each Contributor harmless for any liability
173 incurred by, or claims asserted against, such Contributor by reason
174 of your accepting any such warranty or additional liability.
175
176 END OF TERMS AND CONDITIONS
177
178 APPENDIX: How to apply the Apache License to your work.
179
180 To apply the Apache License to your work, attach the following
181 boilerplate notice, with the fields enclosed by brackets "[]"
182 replaced with your own identifying information. (Don't include
183 the brackets!) The text should be enclosed in the appropriate
184 comment syntax for the file format. We also recommend that a
185 file or class name and description of purpose be included on the
186 same "printed page" as the copyright notice for easier
187 identification within third-party archives.
188
189 Copyright 2016 The libwifi Authors
190
191 Licensed under the Apache License, Version 2.0 (the "License");
192 you may not use this file except in compliance with the License.
193 You may obtain a copy of the License at
194
195 http://www.apache.org/licenses/LICENSE-2.0
196
197 Unless required by applicable law or agreed to in writing, software
198 distributed under the License is distributed on an "AS IS" BASIS,
199 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 See the License for the specific language governing permissions and
201 limitations under the License.
diff --git a/README.md b/README.md new file mode 100644 index 0000000..2be5699 --- /dev/null +++ b/README.md
@@ -0,0 +1,88 @@
1# libwifi
2802.11 Parsing / Generation library
3
4| Build Status | OS | Architecture |
5| ---------------------------------------------------------------------------------- | ------| ------------ |
6|![X86_64](https://github.com/libwifi/libwifi/actions/workflows/x86_64.yml/badge.svg) | Linux | x86_64 |
7
8## What is this?
9libwifi is a C library with a permissive license for generating and parsing a wide variety of 802.11 wireless frames (see the [Feature Checklist](#feature-checklist) below) on Linux with a few lines of straight forward code (see the [Examples section](#examples) below).
10
11It is written with a simple-to-use approach while also exposing features that allow more advanced use, with clean and readable code being a priority. Other goals of the library include cross-architecture support, clean compilation without warnings and strict error checking.
12
13The library is fully documented with code comments in both the headers files and the code files, and also has doxygen HTML documentation in `docs/html`.
14
15## Building and Installing
16### Linux
17```
18$ mkdir build
19$ cd build
20$ cmake ..
21$ make
22$ sudo make install
23```
24
25## Examples
26Some examples are available in the `examples/` directory, which show the general flow of how libwifi is used to generate and parse different types of 802.11 frame.
27
28## Feature Checklist
29- Generation
30 - [X] Radiotap Header
31 - Management
32 - [X] Association Request
33 - [X] Association Response
34 - [X] Reassociation Request
35 - [X] Ressociation Response
36 - [X] Probe Request
37 - [X] Probe Response
38 - [X] Timing Advertisement
39 - [X] Beacon
40 - [X] ATIM
41 - [X] Disassociation
42 - [X] Deauthentication
43 - [X] Action
44 - [X] Action No ACK
45 - Control
46 - [X] RTS (Request-to-Send)
47 - [X] CTS (Clear-to-Send)
48 - Data
49 - [ ] Data Frame
50 - [ ] QoS Data Frame
51 - [ ] EAPOL
52
53- Parsing
54 - [X] Radiotap Header
55 - Management
56 - [X] Association Request
57 - [X] Association Response
58 - [X] Reassociation Request
59 - [X] Ressociation Response
60 - [X] Probe Request
61 - [X] Probe Response
62 - [ ] Timing Advertisement
63 - [X] Beacon
64 - [ ] ATIM
65 - [X] Disassociation
66 - [X] Deauthentication
67 - [ ] Action
68 - [ ] Action No ACK
69 - Control
70 - [ ] RTS (Request-to-Send)
71 - [ ] CTS (Clear-to-Send)
72 - Data
73 - [X] Data Frame (Partial)
74 - [X] QoS Data Frame (Partial)
75 - [X] EAPOL
76
77## Running Tests
78```
79$ cd tests/
80$ mkdir build
81$ cd build
82$ cmake ..
83$ make
84$ sudo iw <interface> set type monitor && sudo ip link set dev <interface> up
85$ ./test-program
86```
87
88
diff --git a/benchmark/Makefile b/benchmark/Makefile new file mode 100644 index 0000000..6dd995d --- /dev/null +++ b/benchmark/Makefile
@@ -0,0 +1,9 @@
1CC=clang
2CFLAGS=-Wall -Werror -O3 -o benchmark_beacon
3LDFLAGS=-lpcap -lwifi
4
5benchmark_beacon: benchmark_beacon.o
6 $(CC) $(CFLAGS) benchmark_beacon.c $(LDFLAGS)
7
8clean:
9 rm benchmark_beacon *.o
diff --git a/benchmark/benchmark_beacon.c b/benchmark/benchmark_beacon.c new file mode 100644 index 0000000..d769be8 --- /dev/null +++ b/benchmark/benchmark_beacon.c
@@ -0,0 +1,37 @@
1#include <libwifi.h>
2
3#include <stdio.h>
4#include <time.h>
5
6// A simple 802.11 Beacon with an SSID and a Channel tag
7#define BEACON_FRAME "\x80\x00\x00\x00\xff\xff\xff\xff" \
8 "\xff\xff\x00\x20\x91\x11\x22\x33" \
9 "\x00\x00\x00\x00\x00\x00\x70\x56" \
10 "\xc6\x90\x20\xe7\x7b\x01\x00\x00" \
11 "\x88\x00\x01\x00\x00\x0e\x6c\x69" \
12 "\x62\x77\x69\x66\x69\x2d\x62\x65" \
13 "\x61\x63\x6f\x6e\x03\x01\x0b"
14
15int main(void) {
16 float times[12] = {0};
17
18 for (int i = 0; i < 12; i++) {
19 float startTime = (float)clock() / CLOCKS_PER_SEC;
20
21 struct libwifi_frame frame;
22 struct libwifi_bss bss;
23 libwifi_get_wifi_frame(&frame, (const unsigned char *)BEACON_FRAME, 56, 0);
24 libwifi_parse_beacon(&bss, &frame);
25
26 float endTime = (float) clock() / CLOCKS_PER_SEC;
27 times[i] = (endTime - startTime);
28
29 libwifi_free_bss(&bss);
30 libwifi_free_wifi_frame(&frame);
31 }
32
33 for (int i = 0; i < 12; i++) {
34 printf("Run %d:\t%9.7f Seconds\n", i+1, times[i]);
35 }
36}
37
diff --git a/examples/generate_beacon/README.md b/examples/generate_beacon/README.md new file mode 100644 index 0000000..4b7103d --- /dev/null +++ b/examples/generate_beacon/README.md
@@ -0,0 +1,19 @@
1# Generating 802.11 Beacons
2This example shows the reader how to generate an 802.11 Beacon, with an SSID and Channel element. It also adds a tagged parameter with the string "libwifi-tag" inside.
3
4# Building and Using
5```
6>> cd examples/generate_beacon/
7>> make
8clang -Wall -Werror -O3 -o generate_beacon -c -o generate_beacon.o generate_beacon.c
9clang -Wall -Werror -O3 -o generate_beacon generate_beacon.c -lpcap -lwifi
10>> ./generate_beacon --file beacon.pcap
11[+] Setup Complete
12[*] Creating Beacon Frame
13[*] Writing Beacon Frame to pcap
14>> tshark -r beacon.pcap
15 1 0.000000 ca:38:6d:6d:3f:bd → Broadcast 802.11 78 Beacon frame, SN=1383, FN=0, Flags=........, BI=100, SSID=libwifi-beacon
16>>
17```
18# Output
19![image](https://user-images.githubusercontent.com/4153572/143600844-ce7dee11-46b0-40a5-a12c-881d79bd584d.png)
diff --git a/examples/generate_beacon/generate_beacon.c b/examples/generate_beacon/generate_beacon.c new file mode 100644 index 0000000..2dad709 --- /dev/null +++ b/examples/generate_beacon/generate_beacon.c
@@ -0,0 +1,80 @@
1#include <libwifi.h>
2
3#include <pcap.h>
4
5#include <bits/types/struct_timeval.h>
6#include <stddef.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <sys/time.h>
11
12pcap_dumper_t *filedumper = NULL;
13
14void create_write_beacon() {
15 printf("[*] Creating Beacon Frame\n");
16 struct libwifi_beacon beacon = {0};
17 unsigned char transmitter[6] = {0};
18
19 libwifi_random_mac(transmitter);
20 unsigned char receiver[6] = "\xFF\xFF\xFF\xFF\xFF\xFF";
21
22 libwifi_create_beacon(&beacon, receiver, transmitter, "libwifi-beacon", 6);
23 libwifi_quick_add_tag(&beacon.tags, TAG_VENDOR_SPECIFIC,
24 (unsigned char *) "libwifi-tag", strlen("libwifi-tag"));
25
26 unsigned char *buf = NULL;
27 size_t buf_len = libwifi_get_beacon_length(&beacon);
28 buf = malloc(buf_len);
29 if (buf == NULL) {
30 fprintf(stderr, "[!] Couldn't allocate buffer for beacon dump.\n");
31 exit(EXIT_FAILURE);
32 }
33 memset(buf, 0, buf_len);
34 libwifi_dump_beacon(&beacon, buf, buf_len);
35
36 printf("[*] Writing Beacon Frame to pcap\n");
37 struct pcap_pkthdr pkt_hdr = {0};
38 struct timeval tv = {0};
39 pkt_hdr.caplen = buf_len;
40 pkt_hdr.len = buf_len;
41 gettimeofday(&tv, NULL);
42 pkt_hdr.ts = tv;
43 pcap_dump((unsigned char *) filedumper, &pkt_hdr, buf);
44}
45
46void helpexit() {
47 fprintf(stderr, "[!] Usage: ./generate_beacon --file <file.pcap>\n");
48 exit(EXIT_FAILURE);
49}
50
51int main(int argc, char **argv) {
52 pcap_t *handle = NULL;
53 char errbuf[PCAP_ERRBUF_SIZE] = {0};
54 FILE *pcapfile = NULL;
55
56 if (argc < 2) {
57 helpexit();
58 }
59 if (strcmp(argv[1], "--file") == 0) {
60 pcapfile = fopen(argv[2], "w+");
61 if ((handle = pcap_open_dead(DLT_IEEE802_11, BUFSIZ)) == NULL) {
62 fprintf(stderr, "[!] Error opening dead capture (%s)\n", errbuf);
63 exit(EXIT_FAILURE);
64 }
65 if ((filedumper = pcap_dump_fopen(handle, pcapfile)) == NULL) {
66 fprintf(stderr, "[!] Error opening file %s (%s)\n", argv[2], errbuf);
67 exit(EXIT_FAILURE);
68 }
69 } else {
70 helpexit();
71 }
72
73 printf("[+] Setup Complete\n");
74
75 create_write_beacon();
76
77 pcap_dump_close(filedumper);
78 pcap_close(handle);
79 return 0;
80}
diff --git a/examples/generate_rtscts/README.md b/examples/generate_rtscts/README.md new file mode 100644 index 0000000..a7db7c2 --- /dev/null +++ b/examples/generate_rtscts/README.md
@@ -0,0 +1,23 @@
1# Generating 802.11 RTS and CTS Frames
2This example shows the reader how to generate an RTS and a CTS Frame, with a random transmitter and a 32ms duration.
3
4# Building and Using
5```
6>> cd examples/generate_rtscts/
7>> make
8clang -Wall -Werror -O3 -o generate_rtscts -c -o generate_rtscts.o generate_rtscts.c
9clang -Wall -Werror -O3 -o generate_rtscts generate_rtscts.c -lpcap -lwifi
10>> ./generate_rtscts --file rtscts.pcap
11[+] Setup Complete
12[*] Creating RTS Frame
13[*] Writing RTS Frame to pcap
14[*] Creating CTS Frame
15[*] Writing CTS Frame to pcap
16>> tshark -r rtscts.pcap
17 1 0.000000 J125Nati_aa:bb:cc (00:20:91:aa:bb:cc) (TA) → Broadcast (ff:ff:ff:ff:ff:ff) (RA) 802.11 16 Request-to-send, Flags=........
18 2 0.000008 → Broadcast (ff:ff:ff:ff:ff:ff) (RA) 802.11 10 Clear-to-send, Flags=........
19>>
20```
21
22# Output
23![image](https://user-images.githubusercontent.com/4153572/143601868-da7e9c99-2534-4fe6-9608-68f5af1ad882.png)
diff --git a/examples/generate_rtscts/generate_rtscts.c b/examples/generate_rtscts/generate_rtscts.c new file mode 100644 index 0000000..f449a06 --- /dev/null +++ b/examples/generate_rtscts/generate_rtscts.c
@@ -0,0 +1,78 @@
1#include <libwifi.h>
2
3#include <pcap.h>
4
5#include <bits/types/struct_timeval.h>
6#include <stddef.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <sys/time.h>
11
12pcap_dumper_t *filedumper = NULL;
13
14void create_write_rtscts() {
15 printf("[*] Creating RTS Frame\n");
16 struct libwifi_rts rts = {0};
17 unsigned char transmitter[6] = "\x00\x20\x91\xAA\xBB\xCC";
18 unsigned char receiver[6] = "\xFF\xFF\xFF\xFF\xFF\xFF";
19 libwifi_create_rts(&rts, transmitter, receiver, 32);
20
21 printf("[*] Writing RTS Frame to pcap\n");
22 struct pcap_pkthdr pkt_hdr = {0};
23 struct timeval tv = {0};
24 pkt_hdr.caplen = sizeof(struct libwifi_rts);
25 pkt_hdr.len = sizeof(struct libwifi_rts);
26 gettimeofday(&tv, NULL);
27 pkt_hdr.ts = tv;
28 pcap_dump((unsigned char *) filedumper, &pkt_hdr, (const unsigned char *) &rts);
29
30 printf("[*] Creating CTS Frame\n");
31 struct libwifi_cts cts = {0};
32 libwifi_create_cts(&cts, receiver, 32);
33
34 printf("[*] Writing CTS Frame to pcap\n");
35 memset(&pkt_hdr, 0, sizeof(struct pcap_pkthdr));
36 memset(&tv, 0, sizeof(struct timeval));
37 pkt_hdr.caplen = sizeof(struct libwifi_cts);
38 pkt_hdr.len = sizeof(struct libwifi_cts);
39 gettimeofday(&tv, NULL);
40 pkt_hdr.ts = tv;
41 pcap_dump((unsigned char *) filedumper, &pkt_hdr, (const unsigned char *) &cts);
42}
43
44void helpexit() {
45 fprintf(stderr, "[!] Usage: ./generate_beacon --file <file.pcap>\n");
46 exit(EXIT_FAILURE);
47}
48
49int main(int argc, char **argv) {
50 pcap_t *handle = NULL;
51 char errbuf[PCAP_ERRBUF_SIZE] = {0};
52 FILE *pcapfile = NULL;
53
54 if (argc < 2) {
55 helpexit();
56 }
57 if (strcmp(argv[1], "--file") == 0) {
58 pcapfile = fopen(argv[2], "w+");
59 if ((handle = pcap_open_dead(DLT_IEEE802_11, BUFSIZ)) == NULL) {
60 fprintf(stderr, "[!] Error opening dead capture (%s)\n", errbuf);
61 exit(EXIT_FAILURE);
62 }
63 if ((filedumper = pcap_dump_fopen(handle, pcapfile)) == NULL) {
64 fprintf(stderr, "[!] Error opening file %s (%s)\n", argv[2], errbuf);
65 exit(EXIT_FAILURE);
66 }
67 } else {
68 helpexit();
69 }
70
71 printf("[+] Setup Complete\n");
72
73 create_write_rtscts();
74
75 pcap_dump_close(filedumper);
76 pcap_close(handle);
77 return 0;
78}
diff --git a/examples/parse_beacon/README.md b/examples/parse_beacon/README.md new file mode 100644 index 0000000..a9b085b --- /dev/null +++ b/examples/parse_beacon/README.md
@@ -0,0 +1,65 @@
1# Parsing 802.11 Beacon Frames
2This example shows the reader how to parse 802.11 Beacons from a pcap, outputting the SSID, BSSID, Channel, Security Information, and more to the terminal.
3
4# Building and Using
5```
6>> cd examples/parse_beacon/
7>> make
8clang -Wall -Werror -O3 -o parse_beacon -c -o parse_beacon.o parse_beacon.c
9clang -Wall -Werror -O3 -o parse_beacon parse_beacon.c -lpcap -lwifi
10>> ./parse_beacon --file ~/beacon.pcap [1/789]
11[+] Setup Complete
12ESSID: libwifi-wpa2/3
13BSSID: 7e:fc:5e:51:93:31
14Receiver: ff:ff:ff:ff:ff:ff
15Transmitter: 7e:fc:5e:51:93:31
16Channel: 11
17WPS: No
18Encryption: WPA3, WPA2
19 Group Ciphers: CCMP128
20 Pairwise Ciphers: CCMP128
21 Auth Key Suites: PSK, SAE
22 MFP Capable: Yes
23Tagged Parameters:
24 Tag: 0 (Size: 14)
25 14 bytes of Tag Data: 6c 69 62 77 69 66 69 2d 77 70 61 32 2f 33
26 Tag: 1 (Size: 8)
27 8 bytes of Tag Data: 82 84 8b 96 24 30 48 6c
28 Tag: 3 (Size: 1)
29 1 bytes of Tag Data: 0b
30 Tag: 5 (Size: 4)
31 4 bytes of Tag Data: 00 02 00 00
32 Tag: 7 (Size: 6)
33 6 bytes of Tag Data: 47 42 20 01 0d 80
34 Tag: 32 (Size: 1)
35 1 bytes of Tag Data: 00
36 Tag: 35 (Size: 2)
37 2 bytes of Tag Data: 10 00
38 Tag: 42 (Size: 1)
39 1 bytes of Tag Data: 00
40 Tag: 50 (Size: 4)
41 4 bytes of Tag Data: 0c 12 18 60
42 Tag: 48 (Size: 24)
43 16 bytes of Tag Data: 01 00 00 0f ac 04 01 00 00 0f ac 04 02 00 00 0f
44 Tag: 45 (Size: 26)
45 16 bytes of Tag Data: 2d 00 1b ff ff 00 00 00 00 00 00 00 00 00 00 00
46 Tag: 61 (Size: 22)
47 16 bytes of Tag Data: 0b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
48 Tag: 127 (Size: 8)
49 8 bytes of Tag Data: 04 00 08 00 00 00 00 40
50 Tag: 255 (Size: 28)
51 16 bytes of Tag Data: 23 01 08 00 1a 00 80 20 20 02 00 0d 00 9e 00 0c
52 Tag: 255 (Size: 7)
53 7 bytes of Tag Data: 24 04 00 00 00 fc ff
54 Tag: 255 (Size: 14)
55 14 bytes of Tag Data: 26 00 03 a4 ff 27 a4 ff 42 43 ff 62 32 ff
56 Tag: 255 (Size: 4)
57 4 bytes of Tag Data: 27 00 00 00
58 Tag: 221 (Size: 30)
59 16 bytes of Tag Data: 00 90 4c 04 08 bf 0c 32 70 81 0f fa ff 00 00 fa
60 Tag: 221 (Size: 10)
61 10 bytes of Tag Data: 00 10 18 02 00 00 1c 00 00 00
62 Tag: 221 (Size: 24)
63 16 bytes of Tag Data: 00 50 f2 02 01 01 00 00 03 a4 00 00 27 a4 00 00
64>>
65```
diff --git a/examples/parse_beacon/parse_beacon.c b/examples/parse_beacon/parse_beacon.c new file mode 100644 index 0000000..4e320b7 --- /dev/null +++ b/examples/parse_beacon/parse_beacon.c
@@ -0,0 +1,158 @@
1#include <libwifi.h>
2
3#include <pcap.h>
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8
9static int has_radiotap = 0;
10
11int print_tag_info(unsigned char *tag_data, size_t tag_data_len) {
12 // Initialise a libwifi_tag_iterator
13 struct libwifi_tag_iterator it = {0};
14 if (libwifi_tag_iterator_init(&it, tag_data, tag_data_len) != 0) {
15 return -1;
16 }
17
18 do {
19 printf("\tTag: %d (Size: %d)\n", it.tag_header->tag_num, it.tag_header->tag_len);
20
21 int max_size = 16;
22 if (it.tag_header->tag_len < 16) {
23 max_size = it.tag_header->tag_len;
24 }
25 printf("\t%d bytes of Tag Data: ", max_size);
26 for (size_t i = 0; i < max_size; i++) {
27 printf("%02x ", it.tag_data[i]);
28 }
29 printf("\n");
30 } while (libwifi_tag_iterator_next(&it) != -1);
31
32 return 0;
33}
34
35void handle_pkt(unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) {
36 unsigned long data_len = header->caplen;
37 unsigned char *data = (unsigned char *) packet;
38
39 // Initialise a libwifi_frame struct and populate it
40 struct libwifi_frame frame = {0};
41 int ret = libwifi_get_wifi_frame(&frame, data, data_len, has_radiotap);
42 if (ret != 0) {
43 return;
44 }
45
46 // Ensure the frame is a Beacon frame
47 if (frame.frame_control.type == TYPE_MANAGEMENT && frame.frame_control.subtype == SUBTYPE_BEACON) {
48 // Initalise a libwifi_bss struct and populate it with the data from the sniffed frame
49 struct libwifi_bss bss = {0};
50 ret = libwifi_parse_beacon(&bss, &frame);
51 if (ret != 0) {
52 return;
53 }
54
55 // Print basic information from the new struct
56 printf("ESSID: %s\n", bss.hidden ? "(hidden)" : bss.ssid);
57 printf("BSSID: " MACSTR "\n", MAC2STR(bss.bssid));
58 printf("Receiver: " MACSTR "\n", MAC2STR(bss.receiver));
59 printf("Transmitter: " MACSTR "\n", MAC2STR(bss.transmitter));
60 printf("Channel: %d\n", bss.channel);
61 printf("WPS: %s\n", bss.wps ? "Yes" : "No");
62
63 // Initialse a char buffer of length LIBWIFI_SECURITY_BUF_LEN, and use libwifi to
64 // write the security suite (WEP, WPA, etc) to it, before printing it.
65 char sec_buf[LIBWIFI_SECURITY_BUF_LEN];
66 libwifi_get_security_type(&bss, sec_buf);
67 printf("Encryption: %s\n", sec_buf);
68
69 // We can re-use the sec_buf buffer for other security related items, since libwifi
70 // will take care of the memory for us.
71 // We'll use the same buffer to get the WPA/2/3 group ciphers from the beacon, if any.
72 libwifi_get_group_ciphers(&bss, sec_buf);
73 printf("\tGroup Ciphers: %s\n", sec_buf);
74
75 // ... and the same for the pairwise ciphers
76 libwifi_get_pairwise_ciphers(&bss, sec_buf);
77 printf("\tPairwise Ciphers: %s\n", sec_buf);
78
79 // ... and the same for the authentication maagement key suites
80 libwifi_get_auth_key_suites(&bss, sec_buf);
81 printf("\tAuth Key Suites: %s\n", sec_buf);
82
83 // Check for enabled RSN Capabilities. In this example, we will check for the
84 // presence of Management Frame Protection (802.11w)
85 if (bss.rsn_info.rsn_capabilities & LIBWIFI_RSN_CAPAB_MFP_CAPABLE) {
86 printf("\tMFP Capable: Yes\n");
87 }
88 if (bss.rsn_info.rsn_capabilities & LIBWIFI_RSN_CAPAB_MFP_REQUIRED) {
89 printf("\tMFP Required: Yes\n");
90 }
91
92 // If any tagged parameters are available for this frame, we can iterate through them
93 // since libwifi will automatically find them.
94 if (bss.tags.length) {
95 printf("Tagged Parameters:\n");
96 print_tag_info(bss.tags.parameters, bss.tags.length);
97 } else {
98 printf("Tagged Parameters: None\n");
99 }
100
101 // Cleanup the libwifi bss
102 libwifi_free_bss(&bss);
103 }
104
105 printf("\n");
106
107 // Clean up the libwifi frame
108 libwifi_free_wifi_frame(&frame);
109}
110
111void helpexit() {
112 fprintf(stderr, "[!] Usage: ./parse_eapol --file <file.pcap>\n");
113 exit(EXIT_FAILURE);
114}
115
116int main(int argc, char **argv) {
117 struct bpf_program *filter = NULL;
118 pcap_t *handle = NULL;
119 pcap_dumper_t *dumper = NULL;
120 char errbuf[PCAP_ERRBUF_SIZE];
121
122 if (argc < 2) {
123 helpexit();
124 }
125 if (strcmp(argv[1], "--file") == 0) {
126 if ((handle = pcap_open_offline(argv[2], errbuf)) == NULL) {
127 fprintf(stderr, "[!] Error opening file %s (%s)\n", argv[2], errbuf);
128 exit(EXIT_FAILURE);
129 }
130 } else {
131 helpexit();
132 }
133
134 int linktype = pcap_datalink(handle);
135 if (linktype == DLT_IEEE802_11_RADIO) {
136 has_radiotap = 1;
137 }
138 if (linktype != DLT_IEEE802_11 && linktype != DLT_IEEE802_11_RADIO) {
139 fprintf(stderr, "[!] 802.11 and radiotap headers not provided (%d)\n", pcap_datalink(handle));
140 pcap_close(handle);
141 exit(EXIT_FAILURE);
142 }
143
144 if ((filter = malloc(sizeof(struct bpf_program))) == NULL) {
145 fprintf(stderr, "[!] There was an error allocating memory for the filter.\n");
146 pcap_close(handle);
147 exit(EXIT_FAILURE);
148 }
149
150 printf("[+] Setup Complete\n");
151
152 dumper = pcap_dump_open(handle, "/tmp/parse_beacon.pcap");
153 pcap_loop(handle, -1 /*INFINITY*/, &handle_pkt, (unsigned char *) dumper);
154
155 pcap_dump_close(dumper);
156 pcap_close(handle);
157 return 0;
158}
diff --git a/examples/parse_eapol/README.md b/examples/parse_eapol/README.md new file mode 100644 index 0000000..4aa206a --- /dev/null +++ b/examples/parse_eapol/README.md
@@ -0,0 +1,74 @@
1# Parsing 802.11 Handshake / EAPOL Frames
2This example shows the reader how to parse 802.11 Handshakes from a pcap, outputting the EAPOL version, type, length, and data such as Nonce, IV, MIC and EAPOL Key Data.
3
4# Building and Using
5```
6>> cd examples/parse_eapol/
7>> make
8clang -Wall -Werror -O3 -o parse_eapol -c -o parse_eapol.o parse_eapol.c
9clang -Wall -Werror -O3 -o parse_eapol parse_eapol.c -lpcap -lwifi
10>> ./parse_eapol --file ~/libwifi-handshake.pcap
11[+] Setup Complete
12WPA Handshake Message: 1 (Message 1)
13EAPOL: Version: 2
14EAPOL: Type: 3
15EAPOL: Length: 95
16EAPOL: Descriptor: 2
17EAPOL: Key Info: Information: 0x008a
18EAPOL: Key Info: Key Length: 16
19EAPOL: Key Info: Replay Counter: 1
20EAPOL: Key Info: Nonce: 43 79 98 09 6a 0e dc 73 8d 44 3b 55 ce b5 47 2c fd 39 0c 87 51 e4 f0 77 d9 5b 5c e1 dc 59 bd 75
21EAPOL: Key Info: IV: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
22EAPOL: Key Info: RSC: 00 00 00 00 00 00 00 00
23EAPOL: Key Info: ID: 00 00 00 00 00 00 00 00
24EAPOL: Key Info: MIC: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
25EAPOL: Key Info: Key Data Length: 0
26
27WPA Handshake Message: 2 (Message 2)
28EAPOL: Version: 1
29EAPOL: Type: 3
30EAPOL: Length: 123
31EAPOL: Descriptor: 2
32EAPOL: Key Info: Information: 0x010a
33EAPOL: Key Info: Key Length: 0
34EAPOL: Key Info: Replay Counter: 1
35EAPOL: Key Info: Nonce: de ed a2 79 e3 c4 96 ba 25 8b ba 84 76 0a 00 69 2e 2c 10 41 24 1a f3 6f 70 9a 4b db 5f 93 47 80
36EAPOL: Key Info: IV: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
37EAPOL: Key Info: RSC: 00 00 00 00 00 00 00 00
38EAPOL: Key Info: ID: 00 00 00 00 00 00 00 00
39EAPOL: Key Info: MIC: 6c 23 fe 8d 68 35 c9 5a 77 82 25 4b 56 41 70 71
40EAPOL: Key Info: Key Data Length: 28
41EAPOL: Key Info: Key Data: 30 1a 01 00 00 0f ac 04 01 00 00 0f ac 04 01 00 00 0f ac 02 80 00 00 00 00 0f ac 06
42
43WPA Handshake Message: 4 (Message 3)
44EAPOL: Version: 2
45EAPOL: Type: 3
46EAPOL: Length: 183
47EAPOL: Descriptor: 2
48EAPOL: Key Info: Information: 0x13ca
49EAPOL: Key Info: Key Length: 16
50EAPOL: Key Info: Replay Counter: 2
51EAPOL: Key Info: Nonce: 43 79 98 09 6a 0e dc 73 8d 44 3b 55 ce b5 47 2c fd 39 0c 87 51 e4 f0 77 d9 5b 5c e1 dc 59 bd 75
52EAPOL: Key Info: IV: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
53EAPOL: Key Info: RSC: 00 00 00 00 00 00 00 00
54EAPOL: Key Info: ID: 00 00 00 00 00 00 00 00
55EAPOL: Key Info: MIC: b7 e7 f1 60 f8 cf 3f ec 8f b3 c5 29 e4 a1 d0 05
56EAPOL: Key Info: Key Data Length: 88
57EAPOL: Key Info: Key Data: 5e b1 a7 ef db 8d 55 06 d5 c8 89 e7 ca 55 ea cf f5 fa 08 18 ef 4e 46 6e b6 3e 62 d1 30 e7 e5 38 ef 2b 37 61 55 03 9e 84 31 75 3e 44 bd 87 12 9c 94 52 db fb 6a 58 4e 1f 94 e0 16 a9 e9 cb 36 48 c8 ed 20 d3 ff 37 a6 7e 12 3f 0b fc 2c a6 cb 72 c3 6a bf 01 32 b1 6e 1b
58
59WPA Handshake Message: 8 (Message 4)
60EAPOL: Version: 1
61EAPOL: Type: 3
62EAPOL: Length: 95
63EAPOL: Descriptor: 2
64EAPOL: Key Info: Information: 0x030a
65EAPOL: Key Info: Key Length: 0
66EAPOL: Key Info: Replay Counter: 2
67EAPOL: Key Info: Nonce: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
68EAPOL: Key Info: IV: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
69EAPOL: Key Info: RSC: 00 00 00 00 00 00 00 00
70EAPOL: Key Info: ID: 00 00 00 00 00 00 00 00
71EAPOL: Key Info: MIC: 13 6e 07 be 17 51 01 e2 03 5d 4c b1 43 e1 4b c7
72EAPOL: Key Info: Key Data Length: 0
73>>
74```
diff --git a/examples/parse_eapol/parse_eapol.c b/examples/parse_eapol/parse_eapol.c new file mode 100644 index 0000000..259ee5f --- /dev/null +++ b/examples/parse_eapol/parse_eapol.c
@@ -0,0 +1,140 @@
1#include <libwifi.h>
2
3#include <pcap.h>
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8
9static int has_radiotap = 0;
10
11void handle_pkt(unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) {
12 unsigned long data_len = header->caplen;
13 unsigned char *data = (unsigned char *) packet;
14
15 // Initialise a libwifi_frame struct and populate it
16 struct libwifi_frame frame = {0};
17 int ret = libwifi_get_wifi_frame(&frame, data, data_len, has_radiotap);
18 if (ret != 0) {
19 return;
20 }
21
22 // Ensure the parsed frame is a data frame
23 if (frame.frame_control.type == TYPE_DATA) {
24 // Ensure the parsed data frame is a WPA handshake
25 if (libwifi_check_wpa_handshake(&frame) > 0) {
26 // Use libwifi to get the EAPOL message part, and also pretty-print it
27 int part = libwifi_check_wpa_message(&frame);
28 printf("WPA Handshake Message: %d (%s)\n", part, libwifi_get_wpa_message_string(&frame));
29
30 // Initlaise a WPA Authentication Data struct and populate it
31 struct libwifi_wpa_auth_data data = {0};
32 libwifi_get_wpa_data(&frame, &data);
33
34 // Print all of the available WPA Auth data
35 printf("EAPOL: Version: %d\n", data.version);
36 printf("EAPOL: Type: %d\n", data.type);
37 printf("EAPOL: Length: %d\n", data.length);
38 printf("EAPOL: Descriptor: %d\n", data.descriptor);
39 printf("EAPOL: Key Info: Information: 0x%04x\n", data.key_info.information);
40 printf("EAPOL: Key Info: Key Length: %d\n", data.key_info.key_length);
41 printf("EAPOL: Key Info: Replay Counter: %lu\n", data.key_info.replay_counter);
42 printf("EAPOL: Key Info: Nonce: ");
43 for (size_t i = 0; i < sizeof(data.key_info.nonce); ++i) {
44 printf("%02x ", data.key_info.nonce[i]);
45 }
46 printf("\n");
47
48 printf("EAPOL: Key Info: IV: ");
49 for (size_t i = 0; i < sizeof(data.key_info.iv); ++i) {
50 printf("%02x ", data.key_info.iv[i]);
51 }
52 printf("\n");
53
54 printf("EAPOL: Key Info: RSC: ");
55 for (size_t i = 0; i < sizeof(data.key_info.rsc); ++i) {
56 printf("%02x ", data.key_info.rsc[i]);
57 }
58 printf("\n");
59
60 printf("EAPOL: Key Info: ID: ");
61 for (size_t i = 0; i < sizeof(data.key_info.id); ++i) {
62 printf("%02x ", data.key_info.id[i]);
63 }
64 printf("\n");
65
66 printf("EAPOL: Key Info: MIC: ");
67 for (size_t i = 0; i < sizeof(data.key_info.mic); ++i) {
68 printf("%02x ", data.key_info.mic[i]);
69 }
70 printf("\n");
71
72 printf("EAPOL: Key Info: Key Data Length: %d\n", data.key_info.key_data_length);
73 if (data.key_info.key_data_length) {
74 printf("EAPOL: Key Info: Key Data: ");
75 for (size_t i = 0; i < data.key_info.key_data_length; ++i) {
76 printf("%02x ", data.key_info.key_data[i]);
77 }
78 printf("\n");
79 }
80
81 // Cleanup the WPA Data
82 libwifi_free_wpa_data(&data);
83
84 printf("\n");
85 }
86 }
87
88 // Clean up the libwifi frame
89 libwifi_free_wifi_frame(&frame);
90}
91
92void helpexit() {
93 fprintf(stderr, "[!] Usage: ./parse_eapol --file <file.pcap>\n");
94 exit(EXIT_FAILURE);
95}
96
97int main(int argc, char **argv) {
98 struct bpf_program *filter = NULL;
99 pcap_t *handle = NULL;
100 pcap_dumper_t *dumper = NULL;
101 char errbuf[PCAP_ERRBUF_SIZE];
102
103 if (argc < 2) {
104 helpexit();
105 }
106 if (strcmp(argv[1], "--file") == 0) {
107 if ((handle = pcap_open_offline(argv[2], errbuf)) == NULL) {
108 fprintf(stderr, "[!] Error opening file %s (%s)\n", argv[2], errbuf);
109 exit(EXIT_FAILURE);
110 }
111 } else {
112 helpexit();
113 }
114
115 int linktype = pcap_datalink(handle);
116 if (linktype == DLT_IEEE802_11_RADIO) {
117 has_radiotap = 1;
118 }
119 if (linktype != DLT_IEEE802_11 && linktype != DLT_IEEE802_11_RADIO) {
120 fprintf(stderr, "[!] 802.11 and radiotap headers not provided (%d)\n", pcap_datalink(handle));
121 pcap_close(handle);
122 exit(EXIT_FAILURE);
123 }
124
125 if ((filter = malloc(sizeof(struct bpf_program))) == NULL) {
126 fprintf(stderr, "[!] There was an error allocating memory for the filter.\n");
127 pcap_close(handle);
128 exit(EXIT_FAILURE);
129 }
130
131 printf("[+] Setup Complete\n");
132
133 dumper = pcap_dump_open(handle, "/tmp/parse_eapol.pcap");
134 pcap_loop(handle, -1 /*INFINITY*/, &handle_pkt, (unsigned char *) dumper);
135
136 pcap_dump_close(dumper);
137 pcap_close(handle);
138
139 return 0;
140}
diff --git a/scripts/generate_entry_header.sh b/scripts/generate_entry_header.sh new file mode 100755 index 0000000..b9e152d --- /dev/null +++ b/scripts/generate_entry_header.sh
@@ -0,0 +1,31 @@
1#!/bin/bash
2
3if [[ ! -d "src/libwifi" ]]; then
4 echo "[!] You must run this script from the project directory root"
5 exit 1
6fi
7
8rm src/libwifi.h
9touch src/libwifi.h
10
11# Generate Header
12cat <<EOF > src/libwifi.h
13#ifndef LIBWIFI_H
14#define LIBWIFI_H
15
16#ifdef __cplusplus
17extern "C" {
18#endif
19
20$(find src -type f -name '*.h' -printf '%P\n' | sed '/libwifi.h/d' | sort | awk '{print "#include \"" $0 "\""}')
21
22#ifdef __cplusplus
23}
24#endif
25
26#endif /* LIBWIFI_H */
27EOF
28
29echo "[!] Generated libwifi entry header!"
30
31exit 0
diff --git a/src/libwifi.h b/src/libwifi.h new file mode 100644 index 0000000..d53789a --- /dev/null +++ b/src/libwifi.h
@@ -0,0 +1,75 @@
1#ifndef LIBWIFI_H
2#define LIBWIFI_H
3
4#ifdef __cplusplus
5extern "C" {
6#endif
7
8#include "libwifi/core/core.h"
9#include "libwifi/core/frame/control/cts.h"
10#include "libwifi/core/frame/control/rts.h"
11#include "libwifi/core/frame/crc.h"
12#include "libwifi/core/frame/data/data.h"
13#include "libwifi/core/frame/frame.h"
14#include "libwifi/core/frame/management/action.h"
15#include "libwifi/core/frame/management/assoc_request.h"
16#include "libwifi/core/frame/management/assoc_response.h"
17#include "libwifi/core/frame/management/atim.h"
18#include "libwifi/core/frame/management/authentication.h"
19#include "libwifi/core/frame/management/beacon.h"
20#include "libwifi/core/frame/management/common.h"
21#include "libwifi/core/frame/management/deauthentication.h"
22#include "libwifi/core/frame/management/disassociation.h"
23#include "libwifi/core/frame/management/probe_request.h"
24#include "libwifi/core/frame/management/probe_response.h"
25#include "libwifi/core/frame/management/reassoc_request.h"
26#include "libwifi/core/frame/management/reassoc_response.h"
27#include "libwifi/core/frame/management/timing_ad.h"
28#include "libwifi/core/frame/tag.h"
29#include "libwifi/core/frame/tag_iterator.h"
30#include "libwifi/core/misc/byteswap.h"
31#include "libwifi/core/misc/epoch.h"
32#include "libwifi/core/misc/llc.h"
33#include "libwifi/core/misc/radiotap.h"
34#include "libwifi/core/misc/security.h"
35#include "libwifi/core/misc/types.h"
36#include "libwifi/core/radiotap/platform.h"
37#include "libwifi/core/radiotap/radiotap.h"
38#include "libwifi/core/radiotap/radiotap_iter.h"
39#include "libwifi/gen/control/cts.h"
40#include "libwifi/gen/control/rts.h"
41#include "libwifi/gen/management/action.h"
42#include "libwifi/gen/management/assoc_request.h"
43#include "libwifi/gen/management/assoc_response.h"
44#include "libwifi/gen/management/atim.h"
45#include "libwifi/gen/management/authentication.h"
46#include "libwifi/gen/management/beacon.h"
47#include "libwifi/gen/management/common.h"
48#include "libwifi/gen/management/deauthentication.h"
49#include "libwifi/gen/management/disassociation.h"
50#include "libwifi/gen/management/probe_request.h"
51#include "libwifi/gen/management/probe_response.h"
52#include "libwifi/gen/management/reassoc_request.h"
53#include "libwifi/gen/management/reassoc_response.h"
54#include "libwifi/gen/management/timing_ad.h"
55#include "libwifi/gen/misc/radiotap.h"
56#include "libwifi/parse/data/data.h"
57#include "libwifi/parse/data/eapol.h"
58#include "libwifi/parse/management/assoc_request.h"
59#include "libwifi/parse/management/assoc_response.h"
60#include "libwifi/parse/management/beacon.h"
61#include "libwifi/parse/management/common.h"
62#include "libwifi/parse/management/deauthentication.h"
63#include "libwifi/parse/management/disassociation.h"
64#include "libwifi/parse/management/probe_request.h"
65#include "libwifi/parse/management/probe_response.h"
66#include "libwifi/parse/management/reassoc_request.h"
67#include "libwifi/parse/management/reassoc_response.h"
68#include "libwifi/parse/misc/radiotap.h"
69#include "libwifi/parse/misc/security.h"
70
71#ifdef __cplusplus
72}
73#endif
74
75#endif /* LIBWIFI_H */
diff --git a/src/libwifi/core/core.c b/src/libwifi/core/core.c new file mode 100644 index 0000000..0340a82 --- /dev/null +++ b/src/libwifi/core/core.c
@@ -0,0 +1,46 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "core.h"
17#include <stdlib.h>
18#include <string.h>
19#include <sys/random.h>
20
21/**
22 * Random MAC addresses, achieved by obtaining 6 bytes of /dev/urandom via getrandom()
23 */
24void libwifi_random_mac(unsigned char buf[6], unsigned char prefix[3]) {
25 memset(buf, 0, 6);
26 if (prefix != NULL) {
27 memcpy(buf, prefix, 3);
28 getrandom(buf + 3, 3, 0);
29 } else {
30 getrandom(buf, 6, 0);
31 }
32}
33
34/**
35 * Dummy linker test function
36 */
37void libwifi_dummy(void) {
38 return;
39}
40
41/**
42 * Version
43 */
44const char *libwifi_get_version(void) {
45 return LIBWIFI_VERSION;
46}
diff --git a/src/libwifi/core/core.h b/src/libwifi/core/core.h new file mode 100644 index 0000000..02e6d45 --- /dev/null +++ b/src/libwifi/core/core.h
@@ -0,0 +1,53 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_H
17#define LIBWIFI_CORE_H
18
19#define LIBWIFI_VERSION "0.0.1"
20
21/**
22 * Commonly used fixed fields
23 */
24#define LIBWIFI_BCAST_MAC "\xFF\xFF\xFF\xFF\xFF\xFF"
25#define LIBWIFI_ZERO_MAC "\x00\x00\x00\x00\x00\x00"
26
27/**
28 * Helpers for MAC Addresses
29 */
30#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
31#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
32
33/**
34 * Function to randomly generate a MAC address.
35 *
36 * @param buf A buffer for the generated MAC to be written to
37 * @param prefix An optional OUI prefix
38 */
39void libwifi_random_mac(unsigned char buf[6], unsigned char prefix[3]);
40
41/**
42 * Dummy function for linker testing purposes.
43 */
44void libwifi_dummy(void);
45
46/**
47 * Obtain the version of libwifi.
48 *
49 * @return The version of the installed libwifi.
50 */
51const char *libwifi_get_version(void);
52
53#endif /* LIBWIFI_CORE_H */
diff --git a/src/libwifi/core/frame/control/cts.h b/src/libwifi/core/frame/control/cts.h new file mode 100644 index 0000000..ecf0007 --- /dev/null +++ b/src/libwifi/core/frame/control/cts.h
@@ -0,0 +1,35 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_CTS_H
17#define LIBWIFI_CORE_CTS_H
18
19#include "../frame.h"
20
21/**
22 * Clear-to-Send Layout
23 * ───────────────────────────────────
24 * ┌─────────────────────────────────┐
25 * │ Header │ Bytes: 4
26 * ├─────────────────────────────────┤
27 * │ Receiver Address │ Bytes: 6
28 * └─────────────────────────────────┘
29 */
30struct libwifi_cts {
31 struct libwifi_ctrl_frame_header frame_header;
32 unsigned char receiver_addr[6];
33};
34
35#endif /* LIBWIFI_CORE_CTS_H */
diff --git a/src/libwifi/core/frame/control/rts.h b/src/libwifi/core/frame/control/rts.h new file mode 100644 index 0000000..0fbaacc --- /dev/null +++ b/src/libwifi/core/frame/control/rts.h
@@ -0,0 +1,38 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_RTS_H
17#define LIBWIFI_CORE_RTS_H
18
19#include "../frame.h"
20
21/**
22 * Request-to-Send Layout
23 * ───────────────────────────────────
24 * ┌─────────────────────────────────┐
25 * │ Header │ Bytes: 4
26 * ├─────────────────────────────────┤
27 * │ Receiver Address │ Bytes: 6
28 * ├─────────────────────────────────┤
29 * │ Transmitter Address │ Bytes: 4
30 * └─────────────────────────────────┘
31 */
32struct libwifi_rts {
33 struct libwifi_ctrl_frame_header frame_header;
34 unsigned char receiver_addr[6];
35 unsigned char transmitter_addr[6];
36};
37
38#endif /* LIBWIFI_CORE_RTS_H */
diff --git a/src/libwifi/core/frame/crc.c b/src/libwifi/core/frame/crc.c new file mode 100644 index 0000000..33dae06 --- /dev/null +++ b/src/libwifi/core/frame/crc.c
@@ -0,0 +1,63 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "crc.h"
17#include "../misc/byteswap.h"
18
19#include <stdint.h>
20#include <sys/types.h>
21
22/*
23 * Basic CRC32 implementation for getting the frame check sum of
24 * a supplied message, usually frame data.
25 */
26uint32_t libwifi_crc32(const unsigned char *message, int message_len) {
27 int i, j;
28 unsigned int byte, crc, mask;
29 i = 0;
30 crc = 0xFFFFFFFF;
31 while (i < message_len) {
32 byte = message[i];
33 crc = crc ^ byte;
34 for (j = 7; j >= 0; j--) {
35 mask = -(crc & 1);
36 crc = (crc >> 1) ^ (0xEDB88320 & mask);
37 }
38 i = i + 1;
39 }
40 return ~crc;
41}
42
43/*
44 * Specific function for calculating a frame FCS, byteswapped for the
45 * host endianess.
46 */
47uint32_t libwifi_calculate_fcs(const unsigned char *frame, size_t frame_len) {
48 return BYTESWAP32(libwifi_crc32(frame, frame_len));
49}
50
51/*
52 * Verify a frame containing a FCS at the end to the FCS calculated
53 * by libwifi.
54 */
55int libwifi_frame_verify(void *frame, size_t frame_len) {
56 uint32_t oCRC = *((uint32_t *) ((char *) frame + frame_len));
57 uint32_t rCRC = libwifi_calculate_fcs(frame, frame_len);
58
59 if (rCRC == oCRC) {
60 return 1;
61 }
62 return 0;
63}
diff --git a/src/libwifi/core/frame/crc.h b/src/libwifi/core/frame/crc.h new file mode 100644 index 0000000..aab1c4e --- /dev/null +++ b/src/libwifi/core/frame/crc.h
@@ -0,0 +1,49 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_CRC_H
17#define LIBWIFI_CORE_CRC_H
18
19#include <stdint.h>
20#include <sys/types.h>
21
22/**
23 * Calculate the CRC32 sum of a given buffer.
24 *
25 * @param message Buffer of data
26 * @param message_len Length of the data buffer
27 * @return CRC32 sum of the given buffer
28 */
29uint32_t libwifi_crc32(const unsigned char *message, int message_len);
30
31/**
32 * Calculate the frame checksum for an 802.11 frame.
33 *
34 * @param frame An 802.11 frame
35 * @param frame_len Length of the frame
36 * @return frame checksum of the frame
37 */
38uint32_t libwifi_calculate_fcs(const unsigned char *frame, size_t frame_len);
39
40/**
41 * Check if the given 802.11 frame has a valid FCS.
42 *
43 * @param frame An 802.11 frame with an FCS
44 * @param frame_len Length of the frame
45 * @return 1 if verified, 0 if not
46 */
47int libwifi_frame_verify(void *frame, size_t frame_len);
48
49#endif /* LIBWIFI_CORE_CRC_H */
diff --git a/src/libwifi/core/frame/data/data.h b/src/libwifi/core/frame/data/data.h new file mode 100644 index 0000000..2eca0ce --- /dev/null +++ b/src/libwifi/core/frame/data/data.h
@@ -0,0 +1,32 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_DATA_H
17#define LIBWIFI_CORE_DATA_H
18
19#include <sys/types.h>
20
21/**
22 * Data Frame Layout
23 * ───────────────────────────────────
24 */
25struct libwifi_data {
26 unsigned char transmitter[6];
27 unsigned char receiver[6];
28 unsigned char *body;
29 size_t body_len;
30};
31
32#endif /* LIBWIFI_CORE_DATA_H */
diff --git a/src/libwifi/core/frame/frame.c b/src/libwifi/core/frame/frame.c new file mode 100644 index 0000000..d885d96 --- /dev/null +++ b/src/libwifi/core/frame/frame.c
@@ -0,0 +1,145 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "frame.h"
17#include "../../parse/misc/radiotap.h"
18#include "../misc/byteswap.h"
19#include "../radiotap/radiotap.h"
20
21#include <errno.h>
22#include <stdlib.h>
23#include <string.h>
24
25/*
26 * Turn sniffed data into a libwifi_frame struct for use with other libwifi functions.
27 *
28 * Supported frames:
29 * - Management Frames (Ordered)
30 * - Management Frames (Unordered)
31 * - Data Frames
32 * - QoS Data Frames
33 * - Control Frames
34 */
35int libwifi_get_wifi_frame(struct libwifi_frame *fi, const unsigned char *frame, size_t frame_len,
36 int radiotap) {
37 union libwifi_frame_header fh = {0};
38 size_t header_len = 0;
39 size_t frame_data_len = frame_len;
40 unsigned char *frame_data = malloc(frame_data_len);
41 memcpy(frame_data, (unsigned char *) frame, frame_data_len);
42
43 if (radiotap) {
44 struct libwifi_radiotap_info rtap_info = {0};
45 libwifi_parse_radiotap_info(&rtap_info, frame_data);
46
47 // Skip forward by the length of the radiotap header
48 frame_data_len -= rtap_info.length;
49 unsigned char *new_data = malloc(frame_data_len);
50 memcpy(new_data, frame_data + rtap_info.length, frame_data_len);
51 free(frame_data);
52 frame_data = new_data;
53
54 // Remove the FCS from the end of the frame data, if present
55 if (rtap_info.flags & IEEE80211_RADIOTAP_F_FCS) {
56 fi->flags |= LIBWIFI_FLAGS_FCS_PRESENT;
57 frame_data_len -= sizeof(uint32_t); // FCS is 4 bytes wide
58 frame_data = realloc(frame_data, frame_data_len);
59 if (frame_data == NULL) {
60 return -ENOMEM;
61 }
62 }
63 }
64
65 struct libwifi_frame_ctrl *frame_control = (struct libwifi_frame_ctrl *) frame_data;
66
67 switch (frame_control->type) {
68 case TYPE_DATA:
69 switch (frame_control->subtype) {
70 case SUBTYPE_DATA_QOS_DATA:
71 case SUBTYPE_DATA_QOS_NULL:
72 case SUBTYPE_DATA_QOS_DATA_CF_ACK:
73 case SUBTYPE_DATA_QOS_DATA_CF_ACK_CF_POLL:
74 case SUBTYPE_DATA_QOS_DATA_CF_POLL:
75 case SUBTYPE_DATA_QOS_CF_ACK_CF_POLL:
76 case SUBTYPE_DATA_QOS_CF_POLL:
77 fi->flags |= LIBWIFI_FLAGS_IS_QOS;
78 break;
79 }
80
81 if (fi->flags & LIBWIFI_FLAGS_IS_QOS) {
82 header_len = sizeof(struct libwifi_data_qos_frame_header);
83 } else {
84 header_len = sizeof(struct libwifi_data_frame_header);
85 }
86
87 if (frame_data_len < header_len) {
88 free(frame_data);
89 return -EINVAL;
90 }
91
92 if (fi->flags & LIBWIFI_FLAGS_IS_QOS) {
93 memset(&fh.data_qos, 0, sizeof(struct libwifi_data_qos_frame_header));
94 memcpy(&fh.data_qos, frame_data, sizeof(struct libwifi_data_qos_frame_header));
95 } else {
96 memset(&fh.data, 0, sizeof(struct libwifi_data_frame_header));
97 memcpy(&fh.data, frame_data, sizeof(struct libwifi_data_frame_header));
98 }
99 break;
100 case TYPE_MANAGEMENT:
101 if (frame_control->flags.ordered) {
102 header_len = sizeof(struct libwifi_mgmt_ordered_frame_header);
103 if (frame_data_len < header_len) {
104 free(frame_data);
105 return -EINVAL;
106 }
107 memcpy(&fh.mgmt_ordered, frame_data, header_len);
108 } else {
109 header_len = sizeof(struct libwifi_mgmt_unordered_frame_header);
110 if (frame_data_len < header_len) {
111 free(frame_data);
112 return -EINVAL;
113 }
114 memcpy(&fh.mgmt_unordered, frame_data, header_len);
115 }
116 break;
117 case TYPE_CONTROL:
118 header_len = sizeof(struct libwifi_ctrl_frame_header);
119 if (frame_data_len < header_len) {
120 free(frame_data);
121 return -EINVAL;
122 }
123 memcpy(&fh.ctrl, frame_data, sizeof(struct libwifi_ctrl_frame_header));
124 break;
125 default:
126 free(frame_data);
127 return -EINVAL;
128 }
129
130 fi->len = frame_data_len;
131 fi->header = fh;
132 fi->header_len = header_len;
133 memcpy(&fi->frame_control, frame_control, sizeof(struct libwifi_frame_ctrl));
134
135 fi->body = malloc(fi->len - fi->header_len);
136 memcpy(fi->body, frame_data + header_len, (fi->len - fi->header_len));
137
138 free(frame_data);
139
140 return 0;
141}
142
143void libwifi_free_wifi_frame(struct libwifi_frame *fi) {
144 free(fi->body);
145}
diff --git a/src/libwifi/core/frame/frame.h b/src/libwifi/core/frame/frame.h new file mode 100644 index 0000000..8c5c89f --- /dev/null +++ b/src/libwifi/core/frame/frame.h
@@ -0,0 +1,334 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_FRAME_H
17#define LIBWIFI_CORE_FRAME_H
18
19#include "../../core/misc/byteswap.h"
20
21#include <stdint.h>
22#include <sys/types.h>
23
24/* libwifi_frame Flags */
25#define LIBWIFI_FLAGS_FCS_PRESENT (1 << 0)
26#define LIBWIFI_FLAGS_IS_QOS (1 << 1)
27
28/* Defined frame types and sub-types */
29enum libwifi_frame_type {
30 TYPE_MANAGEMENT = 0,
31 TYPE_CONTROL = 1,
32 TYPE_DATA = 2,
33 TYPE_EXTENSION = 3,
34};
35enum libwifi_mgmt_subtypes {
36 SUBTYPE_ASSOC_REQ = 0,
37 SUBTYPE_ASSOC_RESP = 1,
38 SUBTYPE_REASSOC_REQ = 2,
39 SUBTYPE_REASSOC_RESP = 3,
40 SUBTYPE_PROBE_REQ = 4,
41 SUBTYPE_PROBE_RESP = 5,
42 SUBTYPE_TIME_ADV = 6,
43 // Reserved = 7,
44 SUBTYPE_BEACON = 8,
45 SUBTYPE_ATIM = 9,
46 SUBTYPE_DISASSOC = 10,
47 SUBTYPE_AUTH = 11,
48 SUBTYPE_DEAUTH = 12,
49 SUBTYPE_ACTION = 13,
50 SUBTYPE_ACTION_NOACK = 14,
51 // Reserved = 15,
52};
53enum libwifi_control_subtypes {
54 // Reserved = 0-3,
55 SUBTYPE_TACK = 3,
56 SUBTYPE_BEAMFORM_REPORT_POLL = 4,
57 SUBTYPE_VHT_NDP_ANNOUNCE = 5,
58 SUBTYPE_CF_EXTENSION = 6,
59 SUBTYPE_WRAPPER = 7,
60 SUBTYPE_BLOCK_ACK_REQ = 8,
61 SUBTYPE_BLOCK_ACK = 9,
62 SUBTYPE_PS_POLL = 10,
63 SUBTYPE_RTS = 11,
64 SUBTYPE_CTS = 12,
65 SUBTYPE_ACK = 13,
66 SUBTYPE_CF_END = 14,
67 SUBTYPE_CF_END_CF_ACK = 15,
68};
69enum libwifi_control_extension_subtypes {
70 // Reserved = 0-1,
71 SUBTYPE_CF_EXT_POLL = 2,
72 SUBTYPE_CF_EXT_SPR = 3,
73 SUBTYPE_CF_EXT_GRANT = 4,
74 SUBTYPE_CF_EXT_DMG_CTS = 5,
75 SUBTYPE_CF_EXT_DMG_DTS = 6,
76 SUBTYPE_CF_EXT_GRANT_ACK = 7,
77 SUBTYPE_CF_EXT_SSW = 8,
78 SUBTYPE_CF_EXT_SSW_FEEDBACK = 9,
79 SUBTYPE_CF_EXT_SSW_ACK = 10,
80 // Reserved = 11-15,
81};
82enum libwifi_data_subtypes {
83 SUBTYPE_DATA = 0,
84 // Reserved = 1-3,
85 SUBTYPE_DATA_NULL = 4,
86 // Reserved = 4-7,
87 SUBTYPE_DATA_QOS_DATA = 8,
88 SUBTYPE_DATA_QOS_DATA_CF_ACK = 9,
89 SUBTYPE_DATA_QOS_DATA_CF_POLL = 10,
90 SUBTYPE_DATA_QOS_DATA_CF_ACK_CF_POLL = 11,
91 SUBTYPE_DATA_QOS_NULL = 12,
92 // Reserved = 13,
93 SUBTYPE_DATA_QOS_CF_POLL = 14,
94 SUBTYPE_DATA_QOS_CF_ACK_CF_POLL = 15,
95};
96enum libwifi_extension_subtypes {
97 SUBTYPE_EXTENSION_DMG_BEACON = 0,
98 SUBTYPE_EXTENSION_SIG_BEACON = 1,
99 // Reserved = 2-15
100};
101
102/*
103 * libwifi Representation of an 802.11 Frame Control Field's Flags.
104 */
105
106struct libwifi_frame_ctrl_flags {
107 unsigned int to_ds : 1;
108 unsigned int from_ds : 1;
109 unsigned int more_frags : 1;
110 unsigned int retry : 1;
111 unsigned int power_mgmt : 1;
112 unsigned int more_data : 1;
113 unsigned int protect : 1;
114 unsigned int ordered : 1;
115} __attribute__((packed));
116
117/*
118 * libwifi Representation of an 802.11 Frame Control Field.
119 */
120struct libwifi_frame_ctrl {
121 unsigned int version : 2;
122 unsigned int type : 2;
123 unsigned int subtype : 4;
124 struct libwifi_frame_ctrl_flags flags;
125} __attribute__((packed));
126
127/*
128 * libwifi Representation of an 802.11 Sequence Control Field.
129 */
130struct libwifi_seq_control {
131 unsigned int fragment_number : 4;
132 unsigned int sequence_number : 12;
133} __attribute__((packed));
134
135/*
136 * libwifi Representation of an 802.11 Data QoS Control Field.
137 *
138 * As the bits of the QoS Control Field can vary depending on other
139 * factors, generic bit names are used here.
140 */
141struct libwifi_qos_control {
142 unsigned int bit1 : 1;
143 unsigned int bit2 : 1;
144 unsigned int bit3 : 1;
145 unsigned int bit4 : 1;
146 unsigned int bit5 : 1;
147 unsigned int bit6 : 1;
148 unsigned int bit7 : 1;
149 unsigned int bit8 : 1;
150 unsigned int bit9 : 1;
151 unsigned int bit10 : 1;
152 unsigned int bit11 : 1;
153 unsigned int bit12 : 1;
154 unsigned int bit13 : 1;
155 unsigned int bit14 : 1;
156 unsigned int bit15 : 1;
157 unsigned int bit16 : 1;
158} __attribute__((packed));
159
160/*
161 * libwifi Representation of an ordered Management Frame header.
162 *
163 * ┌───────────────────────────┐
164 * │ Frame Control Field │ ── 2 Bytes
165 * ├───────────────────────────┤
166 * │ Duration │ ── 2 Bytes
167 * ├───────────────────────────┤
168 * │ Address 1 │ ── 6 Bytes
169 * ├───────────────────────────┤
170 * │ Address 2 │ ── 6 Bytes
171 * ├───────────────────────────┤
172 * │ Address 3 │ ── 6 Bytes
173 * ├───────────────────────────┤
174 * │ Sequence Control │ ── 2 Bytes
175 * ├───────────────────────────┤
176 * │ HT Control │ ── 4 Bytes
177 * └───────────────────────────┘
178 */
179struct libwifi_mgmt_ordered_frame_header {
180 struct libwifi_frame_ctrl frame_control;
181 uint16_t duration;
182 unsigned char addr1[6];
183 unsigned char addr2[6];
184 unsigned char addr3[6];
185 struct libwifi_seq_control seq_control;
186 uint32_t ht_control;
187} __attribute__((packed));
188
189/*
190 * libwifi Representation of an unordered Management Frame header.
191 *
192 * ┌───────────────────────────┐
193 * │ Frame Control Field │ ── 2 Bytes
194 * ├───────────────────────────┤
195 * │ Duration │ ── 2 Bytes
196 * ├───────────────────────────┤
197 * │ Address 1 │ ── 6 Bytes
198 * ├───────────────────────────┤
199 * │ Address 2 │ ── 6 Bytes
200 * ├───────────────────────────┤
201 * │ Address 3 │ ── 6 Bytes
202 * ├───────────────────────────┤
203 * │ Sequence Control │ ── 2 Bytes
204 * └───────────────────────────┘
205 */
206struct libwifi_mgmt_unordered_frame_header {
207 struct libwifi_frame_ctrl frame_control;
208 uint16_t duration;
209 unsigned char addr1[6];
210 unsigned char addr2[6];
211 unsigned char addr3[6];
212 struct libwifi_seq_control seq_control;
213} __attribute__((packed));
214
215/*
216 * libwifi Representation of a Control Frame header.
217 *
218 * ┌───────────────────────────┐
219 * │ Frame Control Field │ ── 2 Bytes
220 * ├───────────────────────────┤
221 * │ Duration │ ── 2 Bytes
222 * └───────────────────────────┘
223 */
224struct libwifi_ctrl_frame_header {
225 struct libwifi_frame_ctrl frame_control;
226 uint16_t duration;
227} __attribute__((packed));
228
229/*
230 * libwifi Representation of a non-QoS Data Frame header.
231 *
232 * ┌───────────────────────────┐
233 * │ Frame Control Field │ ── 2 Bytes
234 * ├───────────────────────────┤
235 * │ Duration │ ── 2 Bytes
236 * ├───────────────────────────┤
237 * │ Address 1 │ ── 6 Bytes
238 * ├───────────────────────────┤
239 * │ Address 2 │ ── 6 Bytes
240 * ├───────────────────────────┤
241 * │ Address 3 │ ── 6 Bytes
242 * ├───────────────────────────┤
243 * │ Sequence Control │ ── 2 Bytes
244 * └───────────────────────────┘
245 */
246struct libwifi_data_frame_header {
247 struct libwifi_frame_ctrl frame_control;
248 uint16_t duration;
249 unsigned char addr1[6];
250 unsigned char addr2[6];
251 unsigned char addr3[6];
252 struct libwifi_seq_control seq_control;
253} __attribute__((packed));
254
255/*
256 * libwifi Representation of a QoS Data Frame header.
257 *
258 * ┌───────────────────────────┐
259 * │ Frame Control Field │ ── 2 Bytes
260 * ├───────────────────────────┤
261 * │ Duration │ ── 2 Bytes
262 * ├───────────────────────────┤
263 * │ Address 1 │ ── 6 Bytes
264 * ├───────────────────────────┤
265 * │ Address 2 │ ── 6 Bytes
266 * ├───────────────────────────┤
267 * │ Address 3 │ ── 6 Bytes
268 * ├───────────────────────────┤
269 * │ Sequence Control │ ── 2 Bytes
270 * ├───────────────────────────┤
271 * │ QoS Control │ ── 2 Bytes
272 * └───────────────────────────┘
273 */
274struct libwifi_data_qos_frame_header {
275 struct libwifi_frame_ctrl frame_control;
276 uint16_t duration;
277 unsigned char addr1[6];
278 unsigned char addr2[6];
279 unsigned char addr3[6];
280 struct libwifi_seq_control seq_control;
281 struct libwifi_qos_control qos_control;
282} __attribute__((packed));
283
284/*
285 * Union of all frame type headers for use with a libwifi_frame struct
286 */
287union libwifi_frame_header {
288 struct libwifi_mgmt_ordered_frame_header mgmt_ordered;
289 struct libwifi_mgmt_unordered_frame_header mgmt_unordered;
290 struct libwifi_ctrl_frame_header ctrl;
291 struct libwifi_data_frame_header data;
292 struct libwifi_data_qos_frame_header data_qos;
293};
294
295/*
296 * Union of all Management Frame headers
297 */
298union libwifi_mgmt_frame_header {
299 struct libwifi_mgmt_ordered_frame_header ordered;
300 struct libwifi_mgmt_unordered_frame_header unordered;
301};
302
303/*
304 * A libwifi_frame struct is used to represent any type of 802.11
305 * frame in libwifi.
306 */
307struct libwifi_frame {
308 uint16_t flags;
309 struct libwifi_frame_ctrl frame_control;
310 size_t len;
311 union libwifi_frame_header header;
312 size_t header_len;
313 unsigned char *body;
314};
315
316/**
317 * Convert a sniffed 802.11 frame into a libwifi_frame.
318 *
319 * @param fi A libwifi_frame struct
320 * @param frame An 802.11 frame
321 * @param frame_len Length of the sniffed 802.11 frame
322 * @return
323 */
324int libwifi_get_wifi_frame(struct libwifi_frame *fi, const unsigned char *frame, size_t frame_len,
325 int radiotap);
326
327/**
328 * Free any dynamically allocated data inside a libwifi_frame.
329 *
330 * @param fi A libwifi_frame struct
331 */
332void libwifi_free_wifi_frame(struct libwifi_frame *fi);
333
334#endif /* LIBWIFI_CORE_FRAME_H */
diff --git a/src/libwifi/core/frame/management/action.h b/src/libwifi/core/frame/management/action.h new file mode 100644 index 0000000..4bd78dd --- /dev/null +++ b/src/libwifi/core/frame/management/action.h
@@ -0,0 +1,93 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_ACTIONS_H
17#define LIBWIFI_CORE_ACTIONS_H
18
19#include "../frame.h"
20#include <stdint.h>
21
22/* Defined action fixed parameter values */
23enum libwifi_actions {
24 ACTION_SPECTRUM_MGMT = 0,
25 ACTION_QOS = 1,
26 // Reserved 2
27 ACTION_BLOCK_ACK = 3,
28 ACTION_PUBLIC = 4,
29 ACTION_RADIO_MEASUREMENT = 5,
30 ACTION_FAST_BSS_TRANSITION = 6,
31 ACTION_HT = 7,
32 ACTION_SA_QUERY = 8,
33 ACTION_PROTECTED_DOPA = 9,
34 ACTION_WNM = 10,
35 ACTION_UNSUPPORTED_WNM = 11,
36 ACTION_TDLS = 12,
37 ACTION_MESH = 13,
38 ACTION_MULTIHOP = 14,
39 ACTION_SELF_PROTECTED = 15,
40 ACTION_DMG = 16,
41 // Reserved 17
42 ACTION_FAST_SESSION_TRANSFER = 18,
43 ACTION_ROBUST_AV_STREAM = 19,
44 ACTION_UNPROTECTED_DMG = 20,
45 ACTION_VHT = 21,
46 ACTION_UNPROTECTED_SIG = 22,
47 ACTION_SIG = 23,
48 ACTION_FLOW_CONTROL = 24,
49 ACTION_CTRL_MCS_NEG = 25,
50 ACTION_FILS = 26,
51 ACTION_CDMG = 27,
52 ACTION_CMMG = 28,
53 ACTION_GLK = 29,
54 // Reserved 30-125
55 ACTION_VENDOR_PROTECTED = 126,
56 ACTION_VENDOR = 127,
57 // Error 128-255
58};
59
60/**
61 * Action Layout
62 * ─────────────────────────────────────
63 * ┌─────────────────────────────────────┐
64 * │ Header │ Bytes: 24
65 * ├─────────────────────────────────────┤
66 * │ Fixed Parameters │ Bytes: Variable
67 * │┌───────────────────────────────────┐│
68 * ││ category ││ Bytes: 1
69 * │├───────────────────────────────────┤│
70 * ││ detail ││ Bytes: Variable
71 * ││┌─────────────────────────────────┐││
72 * │││ tagged parameters │││
73 * ││└─────────────────────────────────┘││
74 * │└───────────────────────────────────┘│
75 * └─────────────────────────────────────┘
76 */
77
78struct libwifi_action_detail {
79 uint8_t detail_length;
80 char *detail;
81} __attribute__((packed));
82
83struct libwifi_action_fixed_parameters {
84 uint8_t category;
85 struct libwifi_action_detail details;
86} __attribute__((packed));
87
88struct libwifi_action {
89 struct libwifi_mgmt_unordered_frame_header frame_header;
90 struct libwifi_action_fixed_parameters fixed_parameters;
91} __attribute__((packed));
92
93#endif /* LIBWIFI_CORE_ACTIONS_H */
diff --git a/src/libwifi/core/frame/management/assoc_request.h b/src/libwifi/core/frame/management/assoc_request.h new file mode 100644 index 0000000..5a35762 --- /dev/null +++ b/src/libwifi/core/frame/management/assoc_request.h
@@ -0,0 +1,51 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_ASSOCREQ_H
17#define LIBWIFI_CORE_ASSOCREQ_H
18
19#include "../frame.h"
20#include "../tag.h"
21#include <stdint.h>
22
23/**
24 * Association Request Layout
25 * ─────────────────────────────────
26 * ┌─────────────────────────────────┐
27 * │ Header │ Bytes: 24
28 * ├─────────────────────────────────┤
29 * │ Fixed Parameters │ Bytes: 4
30 * │┌───────────────────────────────┐│
31 * ││ capabilities ││ Bytes: 2
32 * │├───────────────────────────────┤│
33 * ││ listen interval ││ Bytes: 2
34 * │└───────────────────────────────┘│
35 * ├─────────────────────────────────┤
36 * │ Tagged Parameters │ Bytes: Variable
37 * └─────────────────────────────────┘
38 */
39
40struct libwifi_assoc_req_fixed_parameters {
41 uint16_t capabilities_information;
42 uint16_t listen_interval;
43} __attribute__((packed));
44
45struct libwifi_assoc_req {
46 struct libwifi_mgmt_unordered_frame_header frame_header;
47 struct libwifi_assoc_req_fixed_parameters fixed_parameters;
48 struct libwifi_tagged_parameters tags;
49} __attribute__((packed));
50
51#endif /* LIBWIFI_CORE_ASSOCREQ_H */
diff --git a/src/libwifi/core/frame/management/assoc_response.h b/src/libwifi/core/frame/management/assoc_response.h new file mode 100644 index 0000000..85f5328 --- /dev/null +++ b/src/libwifi/core/frame/management/assoc_response.h
@@ -0,0 +1,54 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_ASSOCRESP_H
17#define LIBWIFI_CORE_ASSOCRESP_H
18
19#include "../frame.h"
20#include "../tag.h"
21#include <stdint.h>
22
23/**
24 * Association Response Layout
25 * ─────────────────────────────────
26 * ┌─────────────────────────────────┐
27 * │ Header │ Bytes: 24
28 * ├─────────────────────────────────┤
29 * │ Fixed Parameters │ Bytes: 6
30 * │┌───────────────────────────────┐│
31 * ││ capabilities ││ Bytes: 2
32 * │├───────────────────────────────┤│
33 * ││ status ││ Bytes: 2
34 * │├───────────────────────────────┤│
35 * ││ association id ││ Bytes: 2
36 * │└───────────────────────────────┘│
37 * ├─────────────────────────────────┤
38 * │ Tagged Parameters │ Bytes: Variable
39 * └─────────────────────────────────┘
40 */
41
42struct libwifi_assoc_resp_fixed_parameters {
43 uint16_t capabilities_information;
44 uint16_t status_code;
45 uint16_t association_id;
46} __attribute__((packed));
47
48struct libwifi_assoc_resp {
49 struct libwifi_mgmt_unordered_frame_header frame_header;
50 struct libwifi_assoc_resp_fixed_parameters fixed_parameters;
51 struct libwifi_tagged_parameters tags;
52} __attribute__((packed));
53
54#endif /* LIBWIFI_CORE_ASSOCRESP_H */
diff --git a/src/libwifi/core/frame/management/atim.h b/src/libwifi/core/frame/management/atim.h new file mode 100644 index 0000000..18a01e2 --- /dev/null +++ b/src/libwifi/core/frame/management/atim.h
@@ -0,0 +1,33 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_ATIM_H
17#define LIBWIFI_CORE_ATIM_H
18
19#include "../frame.h"
20
21/**
22 * ATIM Frame Layout
23 * ─────────────────────────────────
24 * ┌─────────────────────────────────┐
25 * │ Header │ Bytes: 24
26 * └─────────────────────────────────┘
27 */
28
29struct libwifi_atim {
30 struct libwifi_mgmt_unordered_frame_header frame_header;
31};
32
33#endif /* LIBWIFI_CORE_ATIM_H */
diff --git a/src/libwifi/core/frame/management/authentication.h b/src/libwifi/core/frame/management/authentication.h new file mode 100644 index 0000000..c7707c6 --- /dev/null +++ b/src/libwifi/core/frame/management/authentication.h
@@ -0,0 +1,54 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_AUTH_H
17#define LIBWIFI_CORE_AUTH_H
18
19#include "../frame.h"
20#include "../tag.h"
21#include <stdint.h>
22
23/**
24 * Authentication Layout
25 * ─────────────────────────────────
26 * ┌─────────────────────────────────┐
27 * │ Header │ Bytes: 24
28 * ├─────────────────────────────────┤
29 * │ Fixed Parameters │ Bytes: 6
30 * │┌───────────────────────────────┐│
31 * ││ algorithm ││ Bytes: 2
32 * │├───────────────────────────────┤│
33 * ││ transaction ││ Bytes: 2
34 * │├───────────────────────────────┤│
35 * ││ status ││ Bytes: 2
36 * │└───────────────────────────────┘│
37 * ├─────────────────────────────────┤
38 * │ Tagged Parameters │ Bytes: Variable
39 * └─────────────────────────────────┘
40 */
41
42struct libwifi_auth_fixed_parameters {
43 uint16_t algorithm_number;
44 uint16_t transaction_sequence;
45 uint16_t status_code;
46} __attribute__((packed));
47
48struct libwifi_auth {
49 struct libwifi_mgmt_unordered_frame_header frame_header;
50 struct libwifi_auth_fixed_parameters fixed_parameters;
51 struct libwifi_tagged_parameters tags;
52} __attribute__((packed));
53
54#endif /* LIBWIFI_CORE_AUTH_H */
diff --git a/src/libwifi/core/frame/management/beacon.h b/src/libwifi/core/frame/management/beacon.h new file mode 100644 index 0000000..f5c4d72 --- /dev/null +++ b/src/libwifi/core/frame/management/beacon.h
@@ -0,0 +1,54 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_BEACON_H
17#define LIBWIFI_CORE_BEACON_H
18
19#include "../frame.h"
20#include "../tag.h"
21#include <stdint.h>
22
23/**
24 * Beacon Layout
25 * ──────────────────────────────
26 * ┌──────────────────────────────┐
27 * │ Header │ Bytes: 24
28 * ├──────────────────────────────┤
29 * │ Fixed Parameters │ Bytes: 12
30 * │┌────────────────────────────┐│
31 * ││ timestamp ││ Bytes: 4
32 * │├────────────────────────────┤│
33 * ││ interval ││ Bytes: 2
34 * │├────────────────────────────┤│
35 * ││ capabilities ││ Bytes: 2
36 * │└────────────────────────────┘│
37 * ├──────────────────────────────┤
38 * │ Tagged Parameters │ Bytes: Variable
39 * └──────────────────────────────┘
40 */
41
42struct libwifi_beacon_fixed_parameters {
43 uint64_t timestamp;
44 uint16_t beacon_interval;
45 uint16_t capabilities_information;
46} __attribute__((packed));
47
48struct libwifi_beacon {
49 struct libwifi_mgmt_unordered_frame_header frame_header;
50 struct libwifi_beacon_fixed_parameters fixed_parameters;
51 struct libwifi_tagged_parameters tags;
52} __attribute__((packed));
53
54#endif /* LIBWIFI_CORE_BEACON_H */
diff --git a/src/libwifi/core/frame/management/common.h b/src/libwifi/core/frame/management/common.h new file mode 100644 index 0000000..1f5d042 --- /dev/null +++ b/src/libwifi/core/frame/management/common.h
@@ -0,0 +1,101 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_COMMON_H
17#define LIBWIFI_CORE_COMMON_H
18
19#include "../../misc/security.h"
20#include "../tag.h"
21#include <stdint.h>
22#include <stdlib.h>
23
24#define LIBWIFI_BSS 0
25#define LIBWIFI_STA 1
26
27/*
28 * A libwifi_bss struct is used as a common model for BSS / APs, and can be derived
29 * from parsed frames or used to generate new frames. Fields may be optional.
30 *
31 * transmitter - The transmitter MAC address
32 * receiver - The receiver MAC address
33 * bssid - BSSID MAC address
34 * ssid - AP SSID
35 * hidden - Hidden state boolean
36 * channel - BSS Channel
37 * wps - WPS state boolean
38 * encryption_info - Bitfield of encryption state, such as WPA version and ciphers
39 * signal - RSSI in dBm
40 * wpa_info - WPA1 information, present if encryption_info has the WPA1 bit set
41 * rsn_info - WPA2 and/or WPA3 information, present if encryption_info has WPA2 or WPA3 bit set
42 * tags - List of tagged parameters
43 */
44struct libwifi_bss {
45 unsigned char transmitter[6];
46 unsigned char receiver[6];
47 unsigned char bssid[6];
48 char ssid[33];
49 int8_t hidden;
50 uint8_t channel;
51 uint8_t wps;
52 uint64_t encryption_info;
53 int signal;
54 struct libwifi_wpa_info wpa_info;
55 struct libwifi_rsn_info rsn_info;
56 struct libwifi_tagged_parameters tags;
57};
58
59/*
60 * A libwifi_bss can be populated with dynamically allocated tags, which must be free'd by
61 * the user application to avoid memory leaks. This function provides an easy wrapper for any
62 * libwifi allocations made.
63 */
64static inline void libwifi_free_bss(struct libwifi_bss *bss) {
65 free(bss->tags.parameters);
66}
67
68/*
69 * A libwifi_sta struct is used as a common model for stations, roaming or associated,
70 * and can be derived from parsed frames or used to generate new frames. Fields may be optional.
71 *
72 * channel - BSS Channel
73 * randomized - Client has a likely randomized MAC
74 * transmitter - The transmitter MAC address
75 * receiver - The receiver MAC address
76 * bssid - BSSID MAC address
77 * ssid - AP SSID
78 * broadcast_ssid - STA is broadcasting for SSID
79 * tags - List of tagged parameters
80 */
81struct libwifi_sta {
82 uint8_t channel;
83 uint8_t randomized;
84 unsigned char transmitter[6];
85 unsigned char receiver[6];
86 unsigned char bssid[6];
87 char ssid[33];
88 uint8_t broadcast_ssid;
89 struct libwifi_tagged_parameters tags;
90};
91
92/*
93 * A libwifi_sta can be populated with dynamically allocated tags, which must be free'd by
94 * the user application to avoid memory leaks. This function provides an easy wrapper for any
95 * libwifi allocations made.
96 */
97static inline void libwifi_free_sta(struct libwifi_sta *sta) {
98 free(sta->tags.parameters);
99}
100
101#endif /* LIBWIFI_CORE_COMMON_H */
diff --git a/src/libwifi/core/frame/management/deauthentication.h b/src/libwifi/core/frame/management/deauthentication.h new file mode 100644 index 0000000..a01de7c --- /dev/null +++ b/src/libwifi/core/frame/management/deauthentication.h
@@ -0,0 +1,55 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_DEAUTH_H
17#define LIBWIFI_CORE_DEAUTH_H
18
19#include "../frame.h"
20#include "../tag.h"
21#include <stdint.h>
22
23/**
24 * Deauthentication Layout
25 * ──────────────────────────
26 * ┌──────────────────────────┐
27 * │ Header │ Bytes: 24
28 * ├──────────────────────────┤
29 * │ Fixed Parameters │ Bytes: 2
30 * │┌────────────────────────┐│
31 * ││ reason code ││ Bytes: 2
32 * │└────────────────────────┘│
33 * ├──────────────────────────┤
34 * │ Tagged Parameters │ Bytes: Variable
35 * └──────────────────────────┘
36 */
37
38struct libwifi_deauth_fixed_parameters {
39 uint16_t reason_code;
40} __attribute__((packed));
41
42struct libwifi_deauth {
43 struct libwifi_mgmt_unordered_frame_header frame_header;
44 struct libwifi_deauth_fixed_parameters fixed_parameters;
45 struct libwifi_tagged_parameters tags;
46} __attribute__((packed));
47
48struct libwifi_parsed_deauth {
49 int ordered;
50 union libwifi_mgmt_frame_header frame_header;
51 struct libwifi_deauth_fixed_parameters fixed_parameters;
52 struct libwifi_tagged_parameters tags;
53} __attribute__((packed));
54
55#endif /* LIBWIFI_CORE_DEAUTH_H */
diff --git a/src/libwifi/core/frame/management/disassociation.h b/src/libwifi/core/frame/management/disassociation.h new file mode 100644 index 0000000..ec6752a --- /dev/null +++ b/src/libwifi/core/frame/management/disassociation.h
@@ -0,0 +1,55 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_DISASSOC_H
17#define LIBWIFI_CORE_DISASSOC_H
18
19#include "../frame.h"
20#include "../tag.h"
21#include <stdint.h>
22
23/**
24 * Disassociation Layout
25 * ──────────────────────────
26 * ┌──────────────────────────┐
27 * │ Header │ Bytes: 24
28 * ├──────────────────────────┤
29 * │ Fixed Parameters │ Bytes: 2
30 * │┌────────────────────────┐│
31 * ││ reason code ││ Bytes: 2
32 * │└────────────────────────┘│
33 * ├──────────────────────────┤
34 * │ Tagged Parameters │ Bytes: Variable
35 * └──────────────────────────┘
36 */
37
38struct libwifi_disassoc_fixed_parameters {
39 uint16_t reason_code;
40} __attribute__((packed));
41
42struct libwifi_disassoc {
43 struct libwifi_mgmt_unordered_frame_header frame_header;
44 struct libwifi_disassoc_fixed_parameters fixed_parameters;
45 struct libwifi_tagged_parameters tags;
46} __attribute__((packed));
47
48struct libwifi_parsed_disassoc {
49 int ordered;
50 union libwifi_mgmt_frame_header frame_header;
51 struct libwifi_disassoc_fixed_parameters fixed_parameters;
52 struct libwifi_tagged_parameters tags;
53} __attribute__((packed));
54
55#endif /* LIBWIFI_CORE_DISASSOC_H */
diff --git a/src/libwifi/core/frame/management/probe_request.h b/src/libwifi/core/frame/management/probe_request.h new file mode 100644 index 0000000..c54cafa --- /dev/null +++ b/src/libwifi/core/frame/management/probe_request.h
@@ -0,0 +1,38 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_PROBEREQ_H
17#define LIBWIFI_CORE_PROBEREQ_H
18
19#include "../frame.h"
20#include "../tag.h"
21#include <stdint.h>
22
23/**
24 * Probe Request Layout
25 * ──────────────────────────
26 * ┌──────────────────────────┐
27 * │ Header │ Bytes: 24
28 * ├──────────────────────────┤
29 * │ Tagged Parameters │ Bytes: Variable
30 * └──────────────────────────┘
31 */
32
33struct libwifi_probe_req {
34 struct libwifi_mgmt_unordered_frame_header frame_header;
35 struct libwifi_tagged_parameters tags;
36} __attribute__((packed));
37
38#endif /* LIBWIFI_CORE_PROBEREQ_H */
diff --git a/src/libwifi/core/frame/management/probe_response.h b/src/libwifi/core/frame/management/probe_response.h new file mode 100644 index 0000000..f89ae6f --- /dev/null +++ b/src/libwifi/core/frame/management/probe_response.h
@@ -0,0 +1,54 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_PROBERESP_H
17#define LIBWIFI_CORE_PROBERESP_H
18
19#include "../frame.h"
20#include "../tag.h"
21#include <stdint.h>
22
23/**
24 * Probe Response Layout
25 * ──────────────────────────────
26 * ┌──────────────────────────────┐
27 * │ Header │ Bytes: 24
28 * ├──────────────────────────────┤
29 * │ Fixed Parameters │ Bytes: 12
30 * │┌────────────────────────────┐│
31 * ││ timestamp ││ Bytes: 4
32 * │├────────────────────────────┤│
33 * ││ interval ││ Bytes: 2
34 * │├────────────────────────────┤│
35 * ││ capabilities ││ Bytes: 2
36 * │└────────────────────────────┘│
37 * ├──────────────────────────────┤
38 * │ Tagged Parameters │ Bytes: Variable
39 * └──────────────────────────────┘
40 */
41
42struct libwifi_probe_resp_fixed_parameters {
43 uint64_t timestamp;
44 uint16_t probe_resp_interval;
45 uint16_t capabilities_information;
46} __attribute__((packed));
47
48struct libwifi_probe_resp {
49 struct libwifi_mgmt_unordered_frame_header frame_header;
50 struct libwifi_probe_resp_fixed_parameters fixed_parameters;
51 struct libwifi_tagged_parameters tags;
52} __attribute__((packed));
53
54#endif /* LIBWIFI_CORE_PROBERESP_H */
diff --git a/src/libwifi/core/frame/management/reassoc_request.h b/src/libwifi/core/frame/management/reassoc_request.h new file mode 100644 index 0000000..fe5784c --- /dev/null +++ b/src/libwifi/core/frame/management/reassoc_request.h
@@ -0,0 +1,54 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_REASSOCREQ_H
17#define LIBWIFI_CORE_REASSOCREQ_H
18
19#include "../frame.h"
20#include "../tag.h"
21#include <stdint.h>
22
23/**
24 * Reassociation Request Layout
25 * ───────────────────────────────
26 * ┌───────────────────────────────┐
27 * │ Header │ Bytes: 24
28 * ├───────────────────────────────┤
29 * │ Fixed Parameters │ Bytes: 10
30 * │┌─────────────────────────────┐│
31 * ││ capabilities ││ Bytes: 2
32 * │├─────────────────────────────┤│
33 * ││ interval ││ Bytes: 2
34 * │├─────────────────────────────┤│
35 * ││ current AP address ││ Bytes: 6
36 * │└─────────────────────────────┘│
37 * ├───────────────────────────────┤
38 * │ Tagged Parameters │ Bytes: Variable
39 * └───────────────────────────────┘
40 */
41
42struct libwifi_reassoc_req_fixed_parameters {
43 uint16_t capabilities_information;
44 uint16_t listen_interval;
45 unsigned char current_ap_address[6];
46} __attribute__((packed));
47
48struct libwifi_reassoc_req {
49 struct libwifi_mgmt_unordered_frame_header frame_header;
50 struct libwifi_reassoc_req_fixed_parameters fixed_parameters;
51 struct libwifi_tagged_parameters tags;
52} __attribute__((packed));
53
54#endif /* LIBWIFI_CORE_REASSOCREQ_H */
diff --git a/src/libwifi/core/frame/management/reassoc_response.h b/src/libwifi/core/frame/management/reassoc_response.h new file mode 100644 index 0000000..c0b7f62 --- /dev/null +++ b/src/libwifi/core/frame/management/reassoc_response.h
@@ -0,0 +1,54 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_REASSOCRESP_H
17#define LIBWIFI_CORE_REASSOCRESP_H
18
19#include "../frame.h"
20#include "../tag.h"
21#include <stdint.h>
22
23/**
24 * Reassociation Response Layout
25 * ──────────────────────────────────
26 * ┌──────────────────────────────────┐
27 * │ Header │ Bytes: 24
28 * ├──────────────────────────────────┤
29 * │ Fixed Parameters │ Bytes: 6
30 * │┌────────────────────────────────┐│
31 * ││ capabilities ││ Bytes: 2
32 * │├────────────────────────────────┤│
33 * ││ status ││ Bytes: 2
34 * │├────────────────────────────────┤│
35 * ││ association id ││ Bytes: 2
36 * │└────────────────────────────────┘│
37 * ├──────────────────────────────────┤
38 * │ Tagged Parameters │ Bytes: Variable
39 * └──────────────────────────────────┘
40 */
41
42struct libwifi_reassoc_resp_fixed_parameters {
43 uint16_t capabilities_information;
44 uint16_t status_code;
45 uint16_t association_id;
46} __attribute__((packed));
47
48struct libwifi_reassoc_resp {
49 struct libwifi_mgmt_unordered_frame_header frame_header;
50 struct libwifi_reassoc_resp_fixed_parameters fixed_parameters;
51 struct libwifi_tagged_parameters tags;
52} __attribute__((packed));
53
54#endif /* LIBWIFI_CORE_REASSOCRESP_H */
diff --git a/src/libwifi/core/frame/management/timing_ad.h b/src/libwifi/core/frame/management/timing_ad.h new file mode 100644 index 0000000..d0a8ac3 --- /dev/null +++ b/src/libwifi/core/frame/management/timing_ad.h
@@ -0,0 +1,82 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_TIMINGAD_H
17#define LIBWIFI_CORE_TIMINGAD_H
18
19#include <stdint.h>
20#include "../frame.h"
21#include "../tag.h"
22
23/**
24 * Timing Advertisement Layout
25 * ──────────────────────────────────
26 * ┌──────────────────────────────────┐
27 * │ Header │ Bytes: 24
28 * ├──────────────────────────────────┤
29 * │ Fixed Parameters │ Bytes: 6
30 * │┌────────────────────────────────┐│
31 * ││ timestamp ││ Bytes: 8
32 * │├────────────────────────────────┤│
33 * ││ measurement pilot interval ││ Bytes: 1
34 * │├────────────────────────────────┤│
35 * ││ beacon interval ││ Bytes: 2
36 * │├────────────────────────────────┤│
37 * ││ capabilities information ││ Bytes: 2
38 * │├────────────────────────────────┤│
39 * ││ country code ││ Bytes: 3
40 * │├────────────────────────────────┤│
41 * ││ maxmimum regulatory power ││ Bytes: 2
42 * │├────────────────────────────────┤│
43 * ││ maximum transmit power ││ Bytes: 1
44 * │├────────────────────────────────┤│
45 * ││ transmit power used ││ Bytes: 1
46 * │├────────────────────────────────┤│
47 * ││ noise floor ││ Bytes: 1
48 * │└────────────────────────────────┘│
49 * ├──────────────────────────────────┤
50 * │ Tagged Parameters │ Bytes: Variable
51 * │┌────────────────────────────────┐│
52 * ││ timing advert fields ││ Bytes: 17
53 * │└────────────────────────────────┘│
54 * └──────────────────────────────────┘
55 */
56
57struct libwifi_timing_advert_fields {
58 uint8_t timing_capabilities;
59 unsigned char time_value[10];
60 unsigned char time_error[5];
61 unsigned char time_update[1];
62} __attribute__((packed));
63
64struct libwifi_timing_advert_fixed_params {
65 uint64_t timestamp;
66 uint8_t measurement_pilot_interval;
67 uint16_t beacon_interval;
68 uint16_t capabilities_information;
69 char country[3];
70 uint16_t max_reg_power;
71 uint8_t max_tx_power;
72 uint8_t tx_power_used;
73 uint8_t noise_floor;
74} __attribute__((packed));
75
76struct libwifi_timing_advert {
77 struct libwifi_mgmt_unordered_frame_header frame_header;
78 struct libwifi_timing_advert_fixed_params fixed_parameters;
79 struct libwifi_tagged_parameters tags;
80} __attribute__((packed));
81
82#endif /* LIBWIFI_CORE_TIMINGAD_H */
diff --git a/src/libwifi/core/frame/tag.c b/src/libwifi/core/frame/tag.c new file mode 100644 index 0000000..9dec547 --- /dev/null +++ b/src/libwifi/core/frame/tag.c
@@ -0,0 +1,131 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "tag.h"
17#include "tag_iterator.h"
18
19#include <errno.h>
20#include <stdint.h>
21#include <stdlib.h>
22#include <string.h>
23#include <sys/types.h>
24
25int libwifi_add_tag(struct libwifi_tagged_parameters *tags, struct libwifi_tagged_parameter *tag) {
26 // Calculate the total length of the new tag
27 size_t parameter_len = sizeof(struct libwifi_tag_header) + tag->header.tag_len;
28
29 // Initalise the supplied tagged parameters list, if not already done.
30 // Otherwise, extend the allocation to fit the new tag.
31 if (tags->length == 0) {
32 tags->parameters = malloc(parameter_len);
33 if (tags->parameters == NULL) {
34 return -ENOMEM;
35 }
36 } else {
37 void *buf = realloc(tags->parameters, tags->length + parameter_len);
38 if (buf == NULL) {
39 return -ENOMEM;
40 }
41 tags->parameters = buf;
42 }
43
44 // Append the new tag to the list
45 memcpy(tags->parameters + tags->length, &tag->header, sizeof(struct libwifi_tag_header));
46 memcpy(tags->parameters + tags->length + sizeof(struct libwifi_tag_header), tag->body,
47 tag->header.tag_len);
48
49 // Update total tagged parameters length
50 tags->length += parameter_len;
51
52 return 0;
53}
54
55int libwifi_remove_tag(struct libwifi_tagged_parameters *tags, int tag_number) {
56 // Initalise a tag iterator
57 struct libwifi_tag_iterator it = {0};
58 if (libwifi_tag_iterator_init(&it, tags->parameters, tags->length) != 0) {
59 return -EINVAL;
60 }
61
62 // Loop through the tagged parameters list until landing on the supplied tag number
63 do {
64 if (it.tag_header->tag_num == tag_number) {
65 // Calculate the length of the tag we're removing, so that we know
66 // how many bytes to shrink the tagged parameter list by
67 size_t copy_len = tags->length -
68 (it.tag_data - tags->parameters) -
69 (it.tag_header->tag_len + sizeof(struct libwifi_tag_header));
70 memcpy(tags->parameters, it.tag_data + it.tag_header->tag_len, copy_len);
71 size_t new_len = tags->length - it.tag_header->tag_len - sizeof(struct libwifi_tag_header);
72 tags->parameters = realloc(tags->parameters, new_len);
73 tags->length = new_len;
74 break;
75 }
76 } while (libwifi_tag_iterator_next(&it) != -1);
77
78 return 0;
79}
80
81size_t libwifi_create_tag(struct libwifi_tagged_parameter *tagged_parameter, int tag_number,
82 const unsigned char *tag_data, size_t tag_length) {
83 // Initalise the supplied tagged parameter struct
84 memset(tagged_parameter, 0, sizeof(struct libwifi_tagged_parameter));
85 tagged_parameter->header.tag_len = tag_length;
86 tagged_parameter->header.tag_num = tag_number;
87 tagged_parameter->body = malloc(tag_length);
88 if (tagged_parameter->body == NULL) {
89 return -ENOMEM;
90 }
91 memset(tagged_parameter->body, 0, tag_length);
92
93 // Copy the supplied data into the new tag body
94 memcpy(tagged_parameter->body, tag_data, tag_length);
95
96 return sizeof(struct libwifi_tag_header) + tag_length;
97}
98
99void libwifi_free_tag(struct libwifi_tagged_parameter *tagged_parameter) {
100 free(tagged_parameter->body);
101}
102
103size_t libwifi_dump_tag(struct libwifi_tagged_parameter *tag, unsigned char *buf, size_t buf_len) {
104 if (tag->header.tag_len > buf_len) {
105 return -EINVAL;
106 }
107
108 size_t offset = 0;
109
110 memcpy(buf, &tag->header, sizeof(struct libwifi_tag_header));
111 offset += sizeof(struct libwifi_tag_header);
112 memcpy(buf + offset, tag->body, tag->header.tag_len);
113 offset += tag->header.tag_len;
114
115 return sizeof(struct libwifi_tag_header) + tag->header.tag_len;
116}
117
118int libwifi_quick_add_tag(struct libwifi_tagged_parameters *tags, int tag_number,
119 const unsigned char *tag_data, size_t tag_length) {
120 struct libwifi_tagged_parameter tagged_parameter = {0};
121
122 size_t ret = libwifi_create_tag(&tagged_parameter, tag_number, tag_data, tag_length);
123 if (ret <= 0) {
124 return ret;
125 }
126
127 libwifi_add_tag(tags, &tagged_parameter);
128 libwifi_free_tag(&tagged_parameter);
129
130 return 0;
131}
diff --git a/src/libwifi/core/frame/tag.h b/src/libwifi/core/frame/tag.h new file mode 100644 index 0000000..02928fe --- /dev/null +++ b/src/libwifi/core/frame/tag.h
@@ -0,0 +1,306 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_TAG_H
17#define LIBWIFI_CORE_TAG_H
18
19#include <stdint.h>
20#include <sys/types.h>
21
22/* 802.11 Tagged Parameter values */
23enum libwifi_tag_numbers {
24 TAG_SSID = 0,
25 TAG_SUPP_RATES = 1,
26 // Reserved 2
27 TAG_DS_PARAMETER = 3,
28 TAG_CF_PARAMETER = 4,
29 TAG_TIM = 5,
30 TAG_BSS_PARAMETERS = 6,
31 TAG_COUNTRY = 7,
32 // Reserved 8-9
33 TAG_REQUEST = 10,
34 TAG_BSS_LOAD = 11,
35 TAG_EDCA_PARAMETERS = 12,
36 TAG_TSPEC = 13,
37 TAG_TCLAS = 14,
38 TAG_SCHEDULE = 15,
39 TAG_CHALLENGE_TEXT = 16,
40 // Reserved 17-31
41 TAG_POWER_CONSTRAINT = 32,
42 TAG_POWER_CAPABILITY = 33,
43 TAG_TPC_REQUEST = 34,
44 TAG_TPC_REPORT = 35,
45 TAG_SUPPORTED_CHANNELS = 36,
46 TAG_CHANNEL_SWITCH_ANNOUNCEMENT = 37,
47 TAG_MEASUREMENT_REQUEST = 38,
48 TAG_MEASUREMENT_REPORT = 39,
49 TAG_QUIET = 40,
50 TAG_IBSS_DFS = 41,
51 TAG_ERP = 42,
52 TAG_TS_DELAY = 43,
53 TAG_TCLAS_PROCESSING = 44,
54 TAG_HT_CAPABILITIES = 45,
55 TAG_QOS_CAPABILITY = 46,
56 // Reserved 47
57 TAG_RSN = 48,
58 // Reserved 49
59 TAG_EXTENDED_SUPPORTED_RATES = 50,
60 TAG_AP_CHANNEL_REPORT = 51,
61 TAG_NEIGHBOR_REPORT = 52,
62 TAG_RCPI = 53,
63 TAG_MOBILITY_DOMAIN = 54,
64 TAG_FAST_BSS_TRANSITION = 55,
65 TAG_TIMEOUT_INTERVAL = 56,
66 TAG_RIC_DATA = 57,
67 TAG_DSE_REGISTERED_LOCATION = 58,
68 TAG_SUPPORTED_OPERATING_CLASSES = 59,
69 TAG_EXTENDED_CHANNEL_SWITCH_ANNOUNCEMENT = 60,
70 TAG_HT_OPERATION = 61,
71 TAG_SECONDARY_CHANNEL_OFFSET = 62,
72 TAG_BSS_AVERAGE_ACCESS_DELAY = 63,
73 TAG_ANTENNA = 64,
74 TAG_RSNI = 65,
75 TAG_MEASUREMENT_PILOT_TRANSMISSION = 66,
76 TAG_BSS_AVAILABLE_ADMISSION_CAPACITY = 67,
77 TAG_BSS_AC_ACCESS_DELAY = 68,
78 TAG_TIME_ADVERTISEMENT = 69,
79 TAG_RM_ENABLED_CAPABILITIES = 70,
80 TAG_MULTIPLE_BSSID = 71,
81 TAG_BSS_COEXISTENCE = 72,
82 TAG_BSS_INTOLERANT_CHANNEL_REPORT = 73,
83 TAG_OVERLAPPING_BSS_PARAMETERS = 74,
84 TAG_RIC_DESCRIPTOR = 75,
85 TAG_MANAGEMENT_MIC = 76,
86 // Undefined 77
87 TAG_EVENT_REQUEST = 78,
88 TAG_EVENT_REPORT = 79,
89 TAG_DIAGNOSTIC_REQUEST = 80,
90 TAG_DIAGNOSTIC_REPORT = 81,
91 TAG_LOCATION_PARAMTERS = 82,
92 TAG_NONTRANSMITTED_BSSID_CAPABILITY = 83,
93 TAG_SSID_LIST = 84,
94 TAG_MULTIPLE_BSSID_INDEX = 85,
95 TAG_FMS_DESCRIPTOR = 86,
96 TAG_FMS_REQUEST = 87,
97 TAG_FMS_RESPONSE = 88,
98 TAG_QOS_TRAFFIC_CAPABILITY = 89,
99 TAG_BSS_MAX_IDLE_PERIOD = 90,
100 TAG_TFS_REQUEST = 91,
101 TAG_TFS_RESPONSE = 92,
102 TAG_WNM_SLEEP_MODE = 93,
103 TAG_TIM_BROADCAST_REQUEST = 94,
104 TAG_TIM_BROADCAST_RESPONSE = 95,
105 TAG_COLLOCATED_INTERFERENCE_REPORT = 96,
106 TAG_CHANNEL_USAGE = 97,
107 TAG_TIME_ZONE = 98,
108 TAG_DMS_REQUEST = 99,
109 TAG_DMS_RESPONSE = 100,
110 TAG_LINK_IDENTIFIER = 101,
111 TAG_WAKEUP_SCHEDULE = 102,
112 // Undefined 103
113 TAG_CHANNEL_SWITCH_TIMING = 104,
114 TAG_PTI_CONTROL = 105,
115 TAG_TPU_BUFFER_STATUS = 106,
116 TAG_INTERWORKING = 107,
117 TAG_ADVERTISEMENT_PROTOCOL = 108,
118 TAG_EXPEDITED_BANDWIDTH_REQUEST = 109,
119 TAG_QOS_MAP = 110,
120 TAG_ROAMING_CONSORTIUM = 111,
121 TAG_EMERGENCY_ALERT_IDENTIFIER = 112,
122 TAG_MESH_CONFIGURATION = 113,
123 TAG_MESH_ID = 114,
124 TAG_MESH_LINK_METRIC_REPORT = 115,
125 TAG_CONGESTION_NOTIFICATION = 116,
126 TAG_MESH_PEERING_MANAGEMENT = 117,
127 TAG_MESH_CHANNEL_SWITCH_PARAMETERS = 118,
128 TAG_MESH_AWAKE_WINDOW = 119,
129 TAG_BEACON_TIMING = 120,
130 TAG_MCCAOP_SETUP_REQUEST = 121,
131 TAG_MCCAOP_SETUP_REPLY = 122,
132 TAG_MCCAOP_ADVERTISEMENT = 123,
133 TAG_MCCAOP_TEARDOWN = 124,
134 TAG_GANN = 125,
135 TAG_RANN = 126,
136 TAG_EXTENDED_CAPABILITIES = 127,
137 // Reserved 128-129
138 TAG_PREQ = 130,
139 TAG_PREP = 131,
140 TAG_PERR = 132,
141 // Reserved 133-136
142 TAG_PXU = 137,
143 TAG_PXUC = 138,
144 TAG_AUTHENTICATED_MESH_PEERING_EXCHANGE = 139,
145 TAG_MIC = 140,
146 TAG_DESTINATION_URI = 141,
147 TAG_U_APSD_COEXISTENCE = 142,
148 TAG_DMG_WAKEUP_SCHEDULE = 143,
149 TAG_EXTENDED_SCHEDULE = 144,
150 TAG_STA_AVAILABILITY = 145,
151 TAG_DMG_TSPEC = 146,
152 TAG_NEXT_DMG_ATI = 147,
153 // Reserved 149-150
154 TAG_DMG_OPERATION = 151,
155 TAG_DMG_BSS_PARAMETER_CHANGE = 152,
156 TAG_DMG_BEAM_REFINEMENT = 153,
157 TAG_CHANNEL_MEASUREMENT_FEEDBACK = 154,
158 // Reserved 155-156
159 TAG_AWAKE_WINDOW = 157,
160 TAG_MULTI_BAND = 158,
161 TAG_ADDBA_EXTENSION = 159,
162 TAG_NEXTPCP_LIST = 160,
163 TAG_PCP_HANDOVER = 161,
164 TAG_DMG_LINK_MARGIN = 162,
165 TAG_SWITCHING_STREAM = 163,
166 TAG_SESSION_TRANSITION = 164,
167 TAG_DYNAMIC_TONE_PAIRING_REPORT = 165,
168 TAG_CLUSTER_REPORT = 166,
169 TAG_RELAY_CAPABILITIES = 167,
170 TAG_RELAY_TRANSFER_PARAMETER_SET = 168,
171 TAG_BEAMLINK_MAINTENANCE = 169,
172 TAG_MULTIPLE_MAC_SUBLAYERS = 170,
173 TAG_U_PID = 171,
174 TAG_DMG_LINK_ADAPTATION_ACKNOWLEDGEMENT = 172,
175 // Reserved 173
176 TAG_MCCAOP_ADVERTISEMENT_OVERVIEW = 174,
177 TAG_QUIET_PERIOD_REQUEST = 175,
178 // Reserved 176
179 TAG_QUIET_PERIOD_RESPONSE = 177,
180 // Reserved 178-180
181 TAG_QMF_POLICY = 181,
182 TAG_ECAPC_POLICY = 182,
183 TAG_CLUSTER_TIME_OFFSET = 183,
184 TAG_INTRA_ACCESS_CATEGORY_PRIORITY = 184,
185 TAG_SCS_DESCRIPTOR = 185,
186 TAG_QLOAD_REPORT = 186,
187 TAG_HCCA_TXOP_UPDATE_COUNT = 187,
188 TAG_HIGHER_LAYER_STREAM_ID = 188,
189 TAG_GCR_GROUP_ADDRESS = 189,
190 TAG_ANTENNA_SECTOR_ID_PATTERN = 190,
191 TAG_VHT_CAPABILITIES = 191,
192 TAG_VHT_OPERATION = 192,
193 TAG_EXTENDED_BSS_LOAD = 193,
194 TAG_WIDE_BANDWIDTH_CHANNEL_SWITCH = 194,
195 TAG_TRANSMIT_POWER_ENVELOPE = 195,
196 TAG_CHANNEL_SWITCH_WRAPPER = 196,
197 TAG_AID = 197,
198 TAG_QUIET_CHANNEL = 198,
199 TAG_UPSIM = 200,
200 TAG_REDUCED_NEIGHBOR_REPORT = 201,
201 TAG_TVHT_OPERATION = 202,
202 // Reserved 203
203 TAG_DEVICE_LOCATION = 204,
204 TAG_WHITE_SPACE_MAP = 205,
205 TAG_FINE_TIMING_MEASUREMENT_PARAMETERS = 206,
206 // Reserved 207-220
207 TAG_VENDOR_SPECIFIC = 221,
208 // Reserved 222-254
209};
210
211/**
212 * A tagged parameter always consists of a tag number and length
213 */
214struct libwifi_tag_header {
215 uint8_t tag_num;
216 uint8_t tag_len;
217} __attribute__((packed));
218
219/*
220 * A tagged parameter will include a header as well as some body,
221 * depending on the tag number. The length of the body buffer is
222 * determined with the header.tag_len variable.
223 */
224struct libwifi_tagged_parameter {
225 struct libwifi_tag_header header;
226 unsigned char *body;
227} __attribute__((packed));
228
229/*
230 * A collection of total tagged parameters
231 */
232struct libwifi_tagged_parameters {
233 size_t length;
234 unsigned char *parameters;
235} __attribute__((packed));
236
237/*
238 * Vendor specific tagged parameters have an OUI and Sub-Type
239 * to determine their use
240 */
241struct libwifi_tag_vendor_header {
242 unsigned char oui[3];
243 int8_t type;
244} __attribute__((packed));
245
246/**
247 * Add a tagged parameter to a list of frame tagged parameters.
248 *
249 * @param tagged_parameters A management frame's tagged parameters
250 * @param tagged_parameter The new tagged parameter
251 */
252int libwifi_add_tag(struct libwifi_tagged_parameters *tagged_parameters,
253 struct libwifi_tagged_parameter *tagged_parameter);
254
255/**
256 * Remove a tagged parameter from a list of frame tagged parameters.
257 *
258 * @param tagged_parameters A management frame's tagged parameters
259 * @param tag_number Number of the tag to remove
260 */
261int libwifi_remove_tag(struct libwifi_tagged_parameters *tagged_parameters, int tag_number);
262
263/**
264 * Create a tagged parameter from a tag number, length and data.
265 * This can be useful when generating tags on their own, for use with
266 * action frame body's.
267 *
268 * @param tagged_parameter A new tagged parameter struct
269 * @param tag_number Tagged parameter number
270 * @param tag_data The tag body
271 * @param tag_length Length of the tag body
272 * @return length of the created tag
273 */
274size_t libwifi_create_tag(struct libwifi_tagged_parameter *tagged_parameter, int tag_number,
275 const unsigned char *tag_data, size_t tag_length);
276
277/**
278 * Free a tagged parameters body
279 *
280 * @param tagged_parameter A used tagged parameter
281 */
282void libwifi_free_tag(struct libwifi_tagged_parameter *tagged_parameter);
283
284/**
285 * Dump a tagged parameter into a raw buffer, for use with other buffers
286 * or injection.
287 *
288 * @param tag A used tagged parameter struct
289 * @param buf A buffer for the raw data
290 * @param buf_len Length of buf
291 */
292size_t libwifi_dump_tag(struct libwifi_tagged_parameter *tag, unsigned char *buf, size_t buf_len);
293
294/**
295 * Add a tagged parameter via tag number and data to a management frame.
296 *
297 * @param tagged_parameters A management frame's tagged parameters
298 * @param tag_number Tagged parameter to add
299 * @param tag_data Data to copy into new tag
300 * @param tag_length Length of the new tag
301 * @return 0 on success, negative number on error
302 */
303int libwifi_quick_add_tag(struct libwifi_tagged_parameters *tagged_parameters, int tag_number,
304 const unsigned char *tag_data, size_t tag_length);
305
306#endif /* LIBWIFI_CORE_TAG_H */
diff --git a/src/libwifi/core/frame/tag_iterator.c b/src/libwifi/core/frame/tag_iterator.c new file mode 100644 index 0000000..c197752 --- /dev/null +++ b/src/libwifi/core/frame/tag_iterator.c
@@ -0,0 +1,55 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "tag_iterator.h"
17
18#include <errno.h>
19#include <stdio.h>
20#include <string.h>
21
22int libwifi_tag_iterator_init(struct libwifi_tag_iterator *it, const void *tags_start, size_t data_len) {
23 it->tag_header = (struct libwifi_tag_header *) tags_start;
24 if (it->tag_header->tag_len < 0) {
25 return -EINVAL;
26 }
27
28 it->tag_data = (unsigned char *) tags_start + sizeof(struct libwifi_tag_header);
29 it->_next_tag_header = (struct libwifi_tag_header *) (it->tag_data + it->tag_header->tag_len);
30 it->_frame_end = (unsigned char *) (tags_start) + data_len - 1;
31
32 return 0;
33}
34
35int libwifi_tag_iterator_next(struct libwifi_tag_iterator *it) {
36 unsigned char *next_th = (unsigned char *) it->_next_tag_header;
37 if (next_th >= it->_frame_end) {
38 return -1;
39 }
40
41 it->tag_header = it->_next_tag_header;
42 if (it->tag_header->tag_len < 0) {
43 return -1;
44 }
45
46 unsigned long bytes_left = (char *) it->_frame_end - (char *) it->tag_header;
47 if (it->tag_header->tag_len >= bytes_left) {
48 return -1;
49 }
50
51 it->tag_data = ((unsigned char *) (it->tag_header)) + sizeof(struct libwifi_tag_header);
52 it->_next_tag_header = (struct libwifi_tag_header *) (it->tag_data + it->tag_header->tag_len);
53
54 return it->tag_header->tag_num;
55}
diff --git a/src/libwifi/core/frame/tag_iterator.h b/src/libwifi/core/frame/tag_iterator.h new file mode 100644 index 0000000..ae2d4ba --- /dev/null +++ b/src/libwifi/core/frame/tag_iterator.h
@@ -0,0 +1,53 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_TAGITERATOR_H
17#define LIBWIFI_CORE_TAGITERATOR_H
18
19#include "../misc/byteswap.h"
20#include "frame.h"
21#include "tag.h"
22#include <stddef.h>
23
24/**
25 * A libwifi_tag_iterator is used to iterate through a list of tagged parameters
26 * in a wifi frame.
27 */
28struct libwifi_tag_iterator {
29 struct libwifi_tag_header *tag_header;
30 const unsigned char *tag_data;
31 struct libwifi_tag_header *_next_tag_header;
32 const unsigned char *_frame_end;
33};
34
35/**
36 * Initialise a libwifi frame tag iterator.
37 *
38 * @param it A libwifi tag iterator struct
39 * @param tags_start The beginning of a frame's tag data
40 * @param data_len The total length of the frame's tag data
41 * @return negative number on error, zero on success
42 */
43int libwifi_tag_iterator_init(struct libwifi_tag_iterator *it, const void *tags_start, size_t data_len);
44
45/**
46 * Iterate towards the next tagged parameter in a libwifi tag iterator.
47 *
48 * @param A libwifi tag iterator sturct, after being initalised
49 * @return The tag number of the next tag
50 */
51int libwifi_tag_iterator_next(struct libwifi_tag_iterator *it);
52
53#endif /* LIBWIFI_CORE_TAGITERATOR_H */
diff --git a/src/libwifi/core/misc/byteswap.h b/src/libwifi/core/misc/byteswap.h new file mode 100644 index 0000000..cab264f --- /dev/null +++ b/src/libwifi/core/misc/byteswap.h
@@ -0,0 +1,31 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_BYTESWAP_H
17#define LIBWIFI_CORE_BYTESWAP_H
18
19#include <byteswap.h>
20
21#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
22#define BYTESWAP16(x) x
23#define BYTESWAP32(x) x
24#define BYTESWAP64(x) x
25#else
26#define BYTESWAP16(x) (__bswap_16(x))
27#define BYTESWAP32(x) (__bswap_32(x))
28#define BYTESWAP64(x) (__bswap_32(x))
29#endif
30
31#endif /* LIBWIFI_CORE_BYTESWAP_H */
diff --git a/src/libwifi/core/misc/epoch.c b/src/libwifi/core/misc/epoch.c new file mode 100644 index 0000000..d043f06 --- /dev/null +++ b/src/libwifi/core/misc/epoch.c
@@ -0,0 +1,23 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "epoch.h"
17#include <time.h>
18
19unsigned long long libwifi_get_epoch(void) {
20 struct timespec spec;
21 clock_gettime(CLOCK_REALTIME, &spec);
22 return spec.tv_sec * 1000 + spec.tv_nsec / 1000;
23}
diff --git a/src/libwifi/core/misc/epoch.h b/src/libwifi/core/misc/epoch.h new file mode 100644 index 0000000..f8d312f --- /dev/null +++ b/src/libwifi/core/misc/epoch.h
@@ -0,0 +1,26 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_EPOCH_H
17#define LIBWIFI_CORE_EPOCH_H
18
19/**
20 * Get the current system time in epoch.
21 *
22 * @return current time in unix epoch.
23 */
24unsigned long long libwifi_get_epoch(void);
25
26#endif /* LIBWIFI_CORE_EPOCH_H */
diff --git a/src/libwifi/core/misc/llc.h b/src/libwifi/core/misc/llc.h new file mode 100644 index 0000000..9c8350d --- /dev/null +++ b/src/libwifi/core/misc/llc.h
@@ -0,0 +1,33 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_LLC_H
17#define LIBWIFI_CORE_LLC_H
18
19#include <stdint.h>
20
21#define XEROX_OUI "\x00\x00\x00"
22
23#define LLC_TYPE_AUTH 0x888E
24
25struct libwifi_logical_link_ctrl {
26 uint8_t dsap;
27 uint8_t ssap;
28 uint8_t control;
29 unsigned char oui[3];
30 uint16_t type;
31} __attribute__((packed));
32
33#endif /* LIBWIFI_CORE_LLC_H */
diff --git a/src/libwifi/core/misc/radiotap.h b/src/libwifi/core/misc/radiotap.h new file mode 100644 index 0000000..85ed7b8 --- /dev/null +++ b/src/libwifi/core/misc/radiotap.h
@@ -0,0 +1,83 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_RADIOTAP_H
17#define LIBWIFI_CORE_RADIOTAP_H
18
19#include <stdint.h>
20
21#define LIBWIFI_MAX_RADIOTAP_LEN 128
22#define LIBWIFI_MAX_RADIOTAP_ANTENNAS 16
23
24/**
25 * A channel field in radiotap consists of a 2-byte wide flags
26 * sub-field and a 2-byte wide frequency field
27 */
28struct libwifi_radiotap_channel {
29 uint16_t flags;
30 uint16_t freq;
31} __attribute__((packed));
32
33/**
34 * The radiotap antenna field consists of an antenna number and signal in dBm
35 */
36struct libwifi_radiotap_antenna {
37 uint8_t antenna_number;
38 int8_t signal;
39} __attribute__((packed));
40
41/**
42 * The radiotap MCS field is made up of 3 2-byte fields.
43 */
44struct libwifi_radiotap_mcs {
45 uint8_t known;
46 uint8_t flags;
47 uint8_t mcs;
48} __attribute__((packed));
49
50/**
51 * The radiotap timestamp field consists of a timestamp field, accuracy, unit and flags.
52 */
53struct libwifi_radiotap_timestamp {
54 uint64_t timestamp;
55 uint16_t accuracy;
56 uint8_t unit;
57 uint8_t flags;
58} __attribute__((packed));
59
60struct libwifi_radiotap_info {
61 // Header
62 uint32_t present;
63 // Body
64 struct libwifi_radiotap_channel channel;
65 int8_t rate_raw;
66 float rate;
67 uint8_t antenna_count;
68 struct libwifi_radiotap_antenna antennas[LIBWIFI_MAX_RADIOTAP_ANTENNAS];
69 int8_t signal;
70 uint8_t flags;
71 uint32_t extended_flags;
72 uint16_t rx_flags;
73 uint16_t tx_flags;
74 struct libwifi_radiotap_mcs mcs;
75 int8_t tx_power;
76 struct libwifi_radiotap_timestamp timestamp;
77 uint8_t rts_retries;
78 uint8_t data_retries;
79 // Other
80 uint8_t length;
81} __attribute__((packed));
82
83#endif /* LIBWIFI_CORE_RADIOTAP_H */
diff --git a/src/libwifi/core/misc/security.h b/src/libwifi/core/misc/security.h new file mode 100644 index 0000000..6d97b13 --- /dev/null +++ b/src/libwifi/core/misc/security.h
@@ -0,0 +1,289 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_SECURITY_H
17#define LIBWIFI_CORE_SECURITY_H
18
19#include <stdint.h>
20
21/* 802.1X Key Information Field Values */
22#define EAPOL_KEY_INFO_M1 0x008A
23#define EAPOL_KEY_INFO_M2 0x010A
24#define EAPOL_KEY_INFO_M3 0x13CA
25#define EAPOL_KEY_INFO_M4 0x030A
26
27/* Sane maximum value for Cipher Suite Count */
28#define LIBWIFI_MAX_CIPHER_SUITES 6
29
30/* Cipher Suite OUIs for WPA and RSN */
31#define MICROSOFT_OUI "\x00\x50\xF2"
32#define CIPHER_SUITE_OUI "\x00\x0F\xAC"
33
34/* Common Microsoft Vendor Types */
35#define MICROSOFT_OUI_TYPE_WPA 1
36#define MICROSOFT_OUI_TYPE_WMM 2
37#define MICROSOFT_OUI_TYPE_WPS 4
38
39/* Cipher Suite Values */
40#define CIPHER_SUITE_GROUP 0 /* WPA1/2 */
41#define CIPHER_SUITE_WEP40 1 /* WEP */
42#define CIPHER_SUITE_TKIP 2 /* WPA1/2 */
43#define CIPHER_SUITE_RESERVED 3 /* WPA1/2 */
44#define CIPHER_SUITE_CCMP128 4 /* WPA2 */
45#define CIPHER_SUITE_WEP104 5 /* WEP */
46#define CIPHER_SUITE_BIP_CMAC128 6 /* WPA2 */
47#define CIPHER_SUITE_NOTALLOWED 7 /* WPA2 */
48#define CIPHER_SUITE_GCMP128 8 /* WPA3 */
49#define CIPHER_SUITE_GCMP256 9 /* WPA3 */
50#define CIPHER_SUITE_CCMP256 10 /* WPA3 */
51#define CIPHER_SUITE_BIP_GMAC128 11 /* WPA3 */
52#define CIPHER_SUITE_BIP_GMAC256 12 /* WPA3 */
53#define CIPHER_SUITE_BIP_CMAC256 13 /* WPA3 */
54
55/* Auth Key Management Suite Values */
56#define AKM_SUITE_RESERVED 0 /* WPA1/2 */
57#define AKM_SUITE_1X 1 /* WPA1/2 */
58#define AKM_SUITE_PSK 2 /* WPA1/2 */
59#define AKM_SUITE_1X_FT 3 /* WPA1/2 */
60#define AKM_SUITE_PSK_FT 4 /* WPA2 */
61#define AKM_SUITE_1X_SHA256 5 /* WPA2 */
62#define AKM_SUITE_PSK_SHA256 6 /* WPA2 */
63#define AKM_SUITE_TDLS 7 /* WPA2 */
64#define AKM_SUITE_SAE 8 /* WPA3 */
65#define AKM_SUITE_SAE_FT 9 /* WPA3 */
66#define AKM_SUITE_AP_PEER 10 /* WPA3 */
67#define AKM_SUITE_1X_SUITEB_SHA256 11 /* WPA3 */
68#define AKM_SUITE_1X_SUITEB_SHA384 12 /* WPA3 */
69#define AKM_SUITE_1X_FT_SHA384 13 /* WPA3 */
70#define AKM_SUITE_FILS_SHA256 14 /* WPA3 */
71#define AKM_SUITE_FILS_SHA384 15 /* WPA3 */
72#define AKM_SUITE_FILS_SHA256_FT 16 /* WPA3 */
73#define AKM_SUITE_FILS_SHA384_FT 17 /* WPA3 */
74#define AKM_SUITE_OWE 18 /* WPA3 */
75#define AKM_PSK_SHA384_FT 19 /* WPA3 */
76#define AKM_PSK_SHA384 20 /* WPA3 */
77
78/* Authentication Scheme Values */
79#define AUTH_OPEN 0
80#define AUTH_SHARED_KEY 1
81#define AUTH_FAST_BSS 2
82#define AUTH_SAE 3
83#define AUTH_VENDOR 65535
84
85/* libwifi Security Type Values for libwifi_bss encryption_info */
86#define WEP (1ULL << 1)
87#define WPA (1ULL << 2)
88#define WPA2 (1ULL << 3)
89#define WPA3 (1ULL << 4)
90
91/* libwifi Group or Multicast Cipher Values for libwifi_bss encryption_info */
92#define LIBWIFI_GROUP_CIPHER_SUITE_WEP40 (1ULL << 5)
93#define LIBWIFI_GROUP_CIPHER_SUITE_TKIP (1ULL << 6)
94#define LIBWIFI_GROUP_CIPHER_SUITE_RESERVED (1ULL << 7)
95#define LIBWIFI_GROUP_CIPHER_SUITE_CCMP128 (1ULL << 8)
96#define LIBWIFI_GROUP_CIPHER_SUITE_WEP104 (1ULL << 9)
97#define LIBWIFI_GROUP_CIPHER_SUITE_BIP_CMAC128 (1ULL << 10)
98#define LIBWIFI_GROUP_CIPHER_SUITE_NOTALLOWED (1ULL << 11)
99#define LIBWIFI_GROUP_CIPHER_SUITE_GCMP128 (1ULL << 12)
100#define LIBWIFI_GROUP_CIPHER_SUITE_GCMP256 (1ULL << 13)
101#define LIBWIFI_GROUP_CIPHER_SUITE_CCMP256 (1ULL << 14)
102#define LIBWIFI_GROUP_CIPHER_SUITE_BIP_GMAC128 (1ULL << 15)
103#define LIBWIFI_GROUP_CIPHER_SUITE_BIP_GMAC256 (1ULL << 16)
104#define LIBWIFI_GROUP_CIPHER_SUITE_BIP_CMAC256 (1ULL << 17)
105
106/* libwifi Pairwise or Unicast Cipher Values for libwifi_bss encryption_info */
107#define LIBWIFI_PAIRWISE_SUITE_GROUP (1ULL << 18)
108#define LIBWIFI_PAIRWISE_CIPHER_SUITE_WEP40 (1ULL << 19)
109#define LIBWIFI_PAIRWISE_CIPHER_SUITE_TKIP (1ULL << 20)
110#define LIBWIFI_PAIRWISE_CIPHER_SUITE_RESERVED (1ULL << 21)
111#define LIBWIFI_PAIRWISE_CIPHER_SUITE_CCMP128 (1ULL << 22)
112#define LIBWIFI_PAIRWISE_CIPHER_SUITE_WEP104 (1ULL << 23)
113#define LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_CMAC128 (1ULL << 24)
114#define LIBWIFI_PAIRWISE_CIPHER_SUITE_NOTALLOWED (1ULL << 25)
115#define LIBWIFI_PAIRWISE_CIPHER_SUITE_GCMP128 (1ULL << 26)
116#define LIBWIFI_PAIRWISE_CIPHER_SUITE_GCMP256 (1ULL << 27)
117#define LIBWIFI_PAIRWISE_CIPHER_SUITE_CCMP256 (1ULL << 28)
118#define LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_GMAC128 (1ULL << 29)
119#define LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_GMAC256 (1ULL << 30)
120#define LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_CMAC256 (1ULL << 31)
121
122/* libwifi Auth Key Management Values for libwifi_bss encryption_info */
123#define LIBWIFI_AKM_SUITE_RESERVED (1ULL << 32)
124#define LIBWIFI_AKM_SUITE_1X (1ULL << 33)
125#define LIBWIFI_AKM_SUITE_PSK (1ULL << 34)
126#define LIBWIFI_AKM_SUITE_1X_FT (1ULL << 35)
127#define LIBWIFI_AKM_SUITE_PSK_FT (1ULL << 36)
128#define LIBWIFI_AKM_SUITE_1X_SHA256 (1ULL << 37)
129#define LIBWIFI_AKM_SUITE_PSK_SHA256 (1ULL << 39)
130#define LIBWIFI_AKM_SUITE_TDLS (1ULL << 40)
131#define LIBWIFI_AKM_SUITE_SAE (1ULL << 41)
132#define LIBWIFI_AKM_SUITE_SAE_FT (1ULL << 42)
133#define LIBWIFI_AKM_SUITE_AP_PEER (1ULL << 43)
134#define LIBWIFI_AKM_SUITE_1X_SUITEB_SHA256 (1ULL << 44)
135#define LIBWIFI_AKM_SUITE_1X_SUITEB_SHA384 (1ULL << 45)
136#define LIBWIFI_AKM_SUITE_1X_FT_SHA384 (1ULL << 46)
137#define LIBWIFI_AKM_SUITE_FILS_SHA256 (1ULL << 47)
138#define LIBWIFI_AKM_SUITE_FILS_SHA384 (1ULL << 48)
139#define LIBWIFI_AKM_SUITE_FILS_SHA256_FT (1ULL << 49)
140#define LIBWIFI_AKM_SUITE_FILS_SHA384_FT (1ULL << 50)
141#define LIBWIFI_AKM_SUITE_OWE (1ULL << 51)
142#define LIBWIFI_AKM_PSK_SHA384_FT (1ULL << 52)
143#define LIBWIFI_AKM_PSK_SHA384 (1ULL << 53)
144
145/* libwifi Authentication Scheme Values for libwifi_bss encryption_info */
146#define LIBWIFI_AUTH_OPEN (1ULL << 54)
147#define LIBWIFI_AUTH_SHARED_KEY (1ULL << 55)
148#define LIBWIFI_AUTH_FAST_BSS (1ULL << 56)
149#define LIBWIFI_AUTH_SAE (1ULL << 57)
150#define LIBWIFI_AUTH_VENDOR (1ULL << 58)
151
152/* libwifi RSN Capability flags */
153#define LIBWIFI_RSN_CAPAB_PREAUTH (1 << 0)
154#define LIBWIFI_RSN_CAPAB_PAIRWISE (1 << 1)
155#define LIBWIFI_RSN_CAPAB_PTKSA_REPLAY (1 << 2 | 1 << 3)
156#define LIBWIFI_RSN_CAPAB_GTKSA_REPLAY (1 << 4 | 1 << 5)
157#define LIBWIFI_RSN_CAPAB_MFP_REQUIRED (1 << 6)
158#define LIBWIFI_RSN_CAPAB_MFP_CAPABLE (1 << 7)
159#define LIBWIFI_RSN_CAPAB_JOINT_RSNA (1 << 8)
160#define LIBWIFI_RSN_CAPAB_PEERKEY (1 << 9)
161#define LIBWIFI_RSN_CAPAB_EXT_KEY_ID (1 << 13)
162
163/**
164 * libwifi Representation of a WPA or RSN cipher suite
165 * ┌────────────────────────┬────────────┐
166 * │ OUI │ Suite Type │
167 * ├────────────────────────┼────────────┤
168 * │ 3 Bytes │ 1 Byte │
169 * └────────────────────────┴────────────┘
170 *
171 */
172struct libwifi_cipher_suite {
173 unsigned char oui[3];
174 uint8_t suite_type;
175} __attribute__((packed));
176
177/**
178 * libwifi Representation of a Microsoft WPA Information Element
179 * ┌───────────────────────────────────┐
180 * │ Version │ ── 2 Bytes
181 * ├───────────────────────────────────┤
182 * │ Multicast Cipher Suite │ ── 4 Bytes
183 * ├───────────────────────────────────┤
184 * │ Unicast Cipher Suite Count │ ── 2 Bytes
185 * ├───────────────────────────────────┤
186 * │ Unicast Cipher Suites │ ── 4 to 12 Bytes
187 * ├───────────────────────────────────┤
188 * │ Auth Key Management Suite Count │ ── 2 Bytes
189 * ├───────────────────────────────────┤
190 * │ Auth Key Management Suites │ ── 4 to 12 Bytes
191 * └───────────────────────────────────┘
192 */
193struct libwifi_wpa_info {
194 uint16_t wpa_version;
195 struct libwifi_cipher_suite multicast_cipher_suite;
196 uint16_t num_unicast_cipher_suites;
197 struct libwifi_cipher_suite unicast_cipher_suites[LIBWIFI_MAX_CIPHER_SUITES];
198 uint16_t num_auth_key_mgmt_suites;
199 struct libwifi_cipher_suite auth_key_mgmt_suites[LIBWIFI_MAX_CIPHER_SUITES];
200} __attribute__((packed));
201
202/**
203 * libwifi Representation of a 802.11 RSN Information Element
204 * ┌───────────────────────────────────┐
205 * │ Version │ ── 2 Bytes
206 * ├───────────────────────────────────┤
207 * │ Group Cipher Suite │ ── 4 Bytes
208 * ├───────────────────────────────────┤
209 * │ Pairwise Cipher Suite Count │ ── 2 Bytes
210 * ├───────────────────────────────────┤
211 * │ Pairwise Cipher Suites │ ── 4 to 12 Bytes
212 * ├───────────────────────────────────┤
213 * │ Auth Key Management Suite Count │ ── 2 Bytes
214 * ├───────────────────────────────────┤
215 * │ Auth Key Management Suites │ ── 4 to 12 Bytes
216 * ├───────────────────────────────────┤
217 * │ RSN Capabilities │ ── 2 Bytes
218 * └───────────────────────────────────┘
219 */
220struct libwifi_rsn_info {
221 uint16_t rsn_version;
222 struct libwifi_cipher_suite group_cipher_suite;
223 int num_pairwise_cipher_suites;
224 struct libwifi_cipher_suite pairwise_cipher_suites[LIBWIFI_MAX_CIPHER_SUITES];
225 int num_auth_key_mgmt_suites;
226 struct libwifi_cipher_suite auth_key_mgmt_suites[LIBWIFI_MAX_CIPHER_SUITES];
227 uint16_t rsn_capabilities;
228} __attribute__((packed));
229
230/*
231 * libwifi Representation of the 802.1X/EAPOL Key Information section
232 * ┌───────────────────────────────────┐
233 * │ Key Information │ ── 2 Bytes
234 * ├───────────────────────────────────┤
235 * │ Key Length │ ── 2 Bytes
236 * ├───────────────────────────────────┤
237 * │ Replay Counter │ ── 8 Bytes
238 * ├───────────────────────────────────┤
239 * │ WPA Key Nonce │ ── 32 Bytes
240 * ├───────────────────────────────────┤
241 * │ WPA Key IV │ ── 16 Bytes
242 * ├───────────────────────────────────┤
243 * │ WPA Key RSC │ ── 8 Bytes
244 * ├───────────────────────────────────┤
245 * │ WPA Key ID │ ── 8 Bytes
246 * ├───────────────────────────────────┤
247 * │ WPA Key MIC │ ── 16 Bytes
248 * ├───────────────────────────────────┤
249 * │ WPA Key Data Length │ ── 4 Bytes
250 * ├───────────────────────────────────┤
251 * │ WPA Key Data │ ── Variable
252 * └───────────────────────────────────┘
253 */
254struct libwifi_wpa_key_info {
255 uint16_t information;
256 uint16_t key_length;
257 uint64_t replay_counter;
258 unsigned char nonce[32];
259 unsigned char iv[16];
260 unsigned char rsc[8];
261 unsigned char id[8];
262 unsigned char mic[16];
263 uint16_t key_data_length;
264 unsigned char *key_data;
265} __attribute__((packed));
266
267/**
268 * libwifi Representation of the encapsulating 802.1X data in an EAPOL frame
269 * ┌─────────────────┐
270 * │ Version │ ── 1 Byte
271 * ├─────────────────┤
272 * │ Type │ ── 1 Byte
273 * ├─────────────────┤
274 * │ Length │ ── 2 Bytes
275 * ├─────────────────┤
276 * │ Descriptor │ ── 1 Byte
277 * ├─────────────────┤
278 * │ Key Information │ ── See libwifi_wpa_key_info
279 * └─────────────────┘
280 */
281struct libwifi_wpa_auth_data {
282 uint8_t version;
283 uint8_t type;
284 uint16_t length;
285 uint8_t descriptor;
286 struct libwifi_wpa_key_info key_info;
287} __attribute__((packed));
288
289#endif /* LIBWIFI_CORE_SECURITY_H */
diff --git a/src/libwifi/core/misc/types.h b/src/libwifi/core/misc/types.h new file mode 100644 index 0000000..3532183 --- /dev/null +++ b/src/libwifi/core/misc/types.h
@@ -0,0 +1,218 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_CORE_TYPES_H
17#define LIBWIFI_CORE_TYPES_H
18
19#include "../../core/misc/byteswap.h"
20
21/* 802.11 Management Frame "reason code" fixed parameter values */
22enum libwifi_reason_codes {
23 REASON_UNSPECIFIED_FAILURE = 1,
24 REASON_PREVIOUS_AUTH_INVALID = 2,
25 REASON_STA_LEAVING_ESS = 3,
26 REASON_INACTIVE = 4,
27 REASON_TOO_MANY_STAS = 5,
28 REASON_CLASS_2_FRAME = 6,
29 REASON_CLASS_3_FRAME = 7,
30 REASON_STA_LEAVING_BSS = 8,
31 REASON_STA_REQUESTING_REASSOC_NOT_AUTHED = 9,
32 REASON_UNNACCEPTABLE_POWER_CAPABILITY = 10,
33 REASON_UNNACCEPTABLE_CHANNELS = 11,
34 REASON_BSS_TRANSITION_MGMT = 12,
35 REASON_INVALID_ELEMENT = 13,
36 REASON_MIC_FAILURE = 14,
37 REASON_FOURWAY_HANDSHAKE_TIMEOUT = 15,
38 REASON_GROUPKEY_HANDSHAKE_TIMEOUT = 16,
39 REASON_INVALID_FOURWAY = 17,
40 REASON_INVALID_GROUP_CIPHER = 18,
41 REASON_INVALID_PAIRWISE_CIPHER = 19,
42 REASON_INVALID_AKMP = 20,
43 REASON_UNSUPPORTED_RSNE_VERSION = 21,
44 REASON_INVALID_RSNE_CAPABILITIES = 22,
45 REASON_INVALID_8021X_AUTH = 23,
46 REASON_CIPHER_SUITE_REJECTED = 24,
47 REASON_TDLS_DIRECT_LINK_TEARDOWN_UNREACHABLE = 25,
48 REASON_TDLS_DIRECT_LINK_TEARDOWN_UNSPECIFIED = 26,
49 REASON_SSP_REQUEST = 27,
50 REASON_LACKS_SSP_ROAMING = 28,
51 REASON_CIPHER_OR_AKM_REQUIRED = 29,
52 REASON_SERVICE_NOT_AUTHORIZED = 30,
53 REASON_SERVICE_CHANGE_PRECLUDES_TS = 31,
54 REASON_UNSPECIFIED_QOS = 32,
55 REASON_INSUFFICIENT_BANDWIDTH = 33,
56 REASON_EXCESSIVE_ACKS_REQUIRED = 34,
57 REASON_TXOPS_EXCEEDED = 35,
58 REASON_STA_LEAVING = 36,
59 REASON_END_TS = 37,
60 REASON_UNKNOWN_TS_OR_BA = 38,
61 REASON_TIMEOUT = 39,
62 REASON_PEERKEY_MISMATCH = 45,
63 REASON_PEER_INITIATED = 46,
64 REASON_AP_INITIATED = 47,
65 REASON_INVALID_FT_ACTION_FRAMECOUNT = 48,
66 REASON_INVALID_PMKI = 49,
67 REASON_INVALID_MDE = 50,
68 REASON_INVALID_FTE = 51,
69 REASON_MESH_PEERING_CANCELED = 52,
70 REASON_MESH_MAX_PEERS = 53,
71 REASON_MESH_CONFIGURATION_POLICY_VIOLATION = 54,
72 REASON_MESH_CLOSE_RCVD = 55,
73 REASON_MESH_MAX_RETRIES = 56,
74 REASON_MESH_CONFIRM_TIMEOUT = 57,
75 REASON_MESH_INVALID_GTK = 58,
76 REASON_MESH_INCONSISTENT_PARAMETERS = 59,
77 REASON_MESH_INVALID_SECURITY_CAPABILITY = 60,
78 REASON_MESH_PATH_ERROR_NO_PROXY_INFORMATION = 61,
79 REASON_MESH_PATH_ERROR_NO_FORWARDING_INFORMATION = 62,
80 REASON_MESH_PATH_ERROR_DESTINATION_UNREACHABLE = 63,
81 REASON_MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS = 64,
82 REASON_MESH_CHANNEL_SWITCH_REGULATORY_REQUIREMENTS = 65,
83 REASON_MESH_CHANNEL_SWITCH_UNSPECIFIED = 66,
84};
85
86/* 802.11 Management Frame "status code" fixed parameter values */
87enum libwifi_status_codes {
88 STATUS_SUCCESS = 0,
89 STATUS_REFUSED = 1,
90 STATUS_TDLS_REJECTED_ALTERNATIVE_PROVIDED = 2,
91 // Reserved = 4,
92 STATUS_SECURITY_DISABLED = 5,
93 STATUS_UNACCEPTABLE_LIFETIME = 6,
94 STATUS_NOT_IN_SAME_BSS = 7,
95 // Reserved = 8,
96 // Reserved = 9,
97 STATUS_REFUSED_CAPABILITIES_MISMATCH = 10,
98 STATUS_DENIED_NO_ASSOCIATION_EXISTS = 11,
99 STATUS_DENIED_OTHER_REASON = 12,
100 STATUS_UNSUPPORTED_AUTH_ALGORITHM = 13,
101 STATUS_TRANSACTION_SEQUENCE_ERROR = 14,
102 STATUS_CHALLENGE_FAILURE = 15,
103 STATUS_REJECTED_SEQUENCE_TIMEOUT = 16,
104 STATUS_DENIED_NO_MORE_STAS = 17,
105 STATUS_REFUSED_BASIC_RATES_MISMATCH = 18,
106 STATUS_DENIED_NO_SHORT_PREAMBLE_SUPPORT = 19,
107 // Reserved = 20,
108 // Reserved = 21,
109 STATUS_REJECTED_SPECTRUM_MANAGEMENT_REQUIRED = 22,
110 STATUS_REJECTED_BAD_POWER_CAPABILITY = 23,
111 STATUS_REJECTED_BAD_SUPPORTED_CHANNELS = 24,
112 STATUS_DENIED_NO_SHORT_SLOT_TIME_SUPPORT = 25,
113 // Reserved = 26,
114 STATUS_DENIED_NO_HT_SUPPORT = 27,
115 STATUS_R0KH_UNREACHABLE = 28,
116 STATUS_DENIED_PCO_TIME_NOT_SUPPORTED = 29,
117 STATUS_REFUSED_TEMPORARILY = 30,
118 STATUS_ROBUST_MANAGEMENT_POLICY_VIOLATION = 31,
119 STATUS_UNSPECIFIED_QOS_FAILURE = 32,
120 STATUS_DENIED_INSUFFICIENT_BANDWIDTH = 33,
121 STATUS_DENIED_POOR_CHANNEL_CONDITIONS = 34,
122 STATUS_DENIED_QOS_NOT_SUPPORTED = 35,
123 // Reserved = 36,
124 STATUS_REQUEST_DECLINED = 37,
125 STATUS_INVALID_PARAMETERS = 38,
126 STATUS_REJECTED_WITH_SUGGESTED_CHANGES = 39,
127 STATUS_STATUS_INVALID_ELEMENT = 40,
128 STATUS_STATUS_INVALID_GROUP_CIPHER = 41,
129 STATUS_STATUS_INVALID_PAIRWISE_CIPHER = 42,
130 STATUS_STATUS_INVALID_AKMP = 43,
131 STATUS_UNSUPPORTED_RSNE_VERSION = 44,
132 STATUS_INVALID_RSNE_CAPABILITIES = 45,
133 STATUS_STATUS_CIPHER_OUT_OF_POLICY = 46,
134 STATUS_REJECTED_FOR_DELAY_PERIOD = 47,
135 STATUS_DLS_NOT_ALLOWED = 48,
136 STATUS_NOT_PRESENT = 49,
137 STATUS_NOT_QOS_STA = 50,
138 STATUS_DENIED_LISTEN_INTERVAL_TOO_LARGE = 51,
139 STATUS_STATUS_INVALID_FT_ACTION_FRAME_COUNT = 52,
140 STATUS_STATUS_INVALID_PMKID = 53,
141 STATUS_STATUS_INVALID_MDE = 54,
142 STATUS_STATUS_INVALID_FTE = 55,
143 STATUS_REQUESTED_TCLAS_NOT_SUPPORTED = 56,
144 STATUS_INSUFFICIENT_TCLAS_PROCESSING_RESOURCES = 57,
145 STATUS_TRY_ANOTHER_BSS = 58,
146 STATUS_GAS_ADVERTISEMENT_PROTOCOL_NOT_SUPPORTED = 59,
147 STATUS_NO_OUTSTANDING_GAS_REQUEST = 60,
148 STATUS_GAS_RESPONSE_NOT_RECEIVED_FROM = 61,
149 STATUS_GAS_QUERY_TIMEOUT = 62,
150 STATUS_GAS_QUERY_RESPONSE_TOO_ = 63,
151 STATUS_REJECTED_HOME_WITH_SUGGESTED_CHANGES = 64,
152 STATUS_SERVER_UNREACHABLE = 65,
153 // Reserved = 66,
154 STATUS_REJECTED_FOR_SSP_PERMISSIONS = 67,
155 STATUS_REFUSED_UNAUTHENTICATED_ACCESS_NOT_SUPPORTED = 68,
156 // Reserved = 69,
157 // Reserved = 70,
158 // Reserved = 71,
159 STATUS_INVALID_RSNE = 72,
160 STATUS_U_APSD_COEXISTANCE_NOT_SUPPORTED = 73,
161 STATUS_U_APSD_COEX_MODE_NOT_SUPPORTED = 74,
162 STATUS_BAD_INTERVAL_WITH_U_APSD_COEX = 75,
163 STATUS_ANTI_CLOGGING_TOKEN_REQUIRED = 76,
164 STATUS_UNSUPPORTED_FINITE_CYCLIC_GROUP = 77,
165 STATUS_CANNOT_FIND_ALTERNATIVE_TBTT = 78,
166 STATUS_TRANSMISSION_FAILURE = 79,
167 STATUS_REQUESTED_TCLAS_NOT_SUPPORTED_2 = 80,
168 STATUS_TCLAS_RESOURCES_EXHAUSTED = 81,
169 STATUS_REJECTED_WITH_SUGGESTED_BSS_TRANSITION = 82,
170 STATUS_REJECT_WITH_SCHEDULE = 83,
171 STATUS_REJECT_NO_WAKEUP_SPECIFIED = 84,
172 STATUS_SUCCESS_POWER_SAVE_MODE = 85,
173 STATUS_PENDING_ADMITTING_FST_SESSION = 86,
174 STATUS_PERFORMING_FST_NOW = 87,
175 STATUS_PENDING_GAP_IN_BA_WINDOW = 88,
176 STATUS_REJECT_U_PID_SETTING = 89,
177 // Reserved = 90,
178 // Reserved = 91,
179 STATUS_REFUSED_EXTERNAL_REASON = 92,
180 STATUS_REFUSED_AP_OUT_OF_MEMORY = 93,
181 STATUS_REJECTED_EMERGENCY_SERVICES_NOT_SUPPORTED = 94,
182 STATUS_QUERY_RESPONSE_OUTSTANDING = 95,
183 STATUS_REJECT_DSE_BAND = 96,
184 STATUS_TCLAS_PROCESSING_TERMINATED = 97,
185 STATUS_TS_SCHEDULE_CONFLICT = 98,
186 STATUS_DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL = 99,
187 STATUS_MCCAOP_RESERVATION_CONFLICT = 100,
188 STATUS_MAF_LIMIT_EXCEEDED = 101,
189 STATUS_MCCA_TRACK_LIMIT_EXCEEDED = 102,
190 STATUS_DENIED_DUE_TO_SPECTRUM_MANAGEMENT = 103,
191 STATUS_DENIED_VHT_NOT_SUPPORTED = 104,
192 STATUS_ENABLEMENT_DENIED = 105,
193 STATUS_RESTRICTION_FROM_AUTHORIZED_GDB = 106,
194 STATUS_AUTHORIZATION_DEENABLED = 107,
195 // Reserved = 108–65535
196};
197
198/* Defined capabilities_information fixed parameter values */
199#define libwifi_check_capabilities(x, cap) (BYTESWAP16(x) & (1 << cap))
200enum libwifi_capabilities {
201 CAPABILITIES_ESS = 0,
202 CAPABILITIES_IBSS = 1,
203 CAPABILITIES_POLL = 2,
204 CAPABILITIES_POLL_REQ = 3,
205 CAPABILITIES_PRIVACY = 4,
206 CAPABILITIES_SHORT_PREAMBLE = 5,
207 CAPABILITIES_PBCC = 6,
208 CAPABILITIES_CHAN_AGILITY = 7,
209 CAPABILITIES_SPECTRUM_AGILITY = 8 & (8 >> 1),
210 CAPABILITIES_SHORT_SLOT = 10,
211 CAPABILITIES_POWER_SAVE = 11,
212 CAPABILITIES_MEASUREMENT = 12,
213 CAPABILITIES_DSSS_OFDM = 13,
214 CAPABILITIES_DELAYED_ACK = 14,
215 CAPABILITIES_IMMEDIATE_ACK = 15,
216};
217
218#endif /* LIBWIFI_CORE_TYPES_H */
diff --git a/src/libwifi/core/radiotap/COPYING b/src/libwifi/core/radiotap/COPYING new file mode 100644 index 0000000..4cc12c2 --- /dev/null +++ b/src/libwifi/core/radiotap/COPYING
@@ -0,0 +1,14 @@
1Copyright (c) 2007-2009 Andy Green <andy@warmcat.com>
2Copyright (c) 2007-2009 Johannes Berg <johannes@sipsolutions.net>
3
4Permission to use, copy, modify, and/or distribute this software for any
5purpose with or without fee is hereby granted, provided that the above
6copyright notice and this permission notice appear in all copies.
7
8THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/src/libwifi/core/radiotap/platform.h b/src/libwifi/core/radiotap/platform.h new file mode 100644 index 0000000..e0ad99f --- /dev/null +++ b/src/libwifi/core/radiotap/platform.h
@@ -0,0 +1,81 @@
1#include <errno.h>
2#include <stddef.h>
3#include <string.h>
4
5#if defined(linux) || defined(Linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux__)
6#include <endian.h>
7#if defined(__UCLIBC__)
8#include <asm/byteorder.h>
9#ifndef le16toh
10#define le16toh __le16_to_cpu
11#endif
12#ifndef le32toh
13#define le32toh __le32_to_cpu
14#endif
15#endif
16#endif
17
18#if defined(__CYGWIN32__) || defined(CYGWIN)
19#include <asm/byteorder.h>
20#include <endian.h>
21#endif
22
23#if defined(__APPLE__)
24#include <machine/endian.h>
25#endif
26
27#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__) || defined(__MidnightBSD__) || \
28 defined(__NetBSD__)
29#include <sys/endian.h>
30#include <sys/types.h>
31#endif
32
33#if defined(__SVR4) && defined(__sun__)
34#include <sys/byteorder.h>
35#include <sys/types.h>
36#endif
37
38#ifndef le16_to_cpu
39#define le16_to_cpu le16toh
40#endif
41
42#ifndef le32_to_cpu
43#define le32_to_cpu le32toh
44#endif
45
46#if defined(_MSC_VER)
47// Microsoft
48#define EXPORT __declspec(dllexport)
49#define IMPORT __declspec(dllimport)
50#elif defined(__GNUC__) || defined(__llvm__) || defined(__clang__) || defined(__INTEL_COMPILER)
51#define EXPORT __attribute__((visibility("default")))
52#define IMPORT
53#else
54// do nothing and hope for the best?
55#define EXPORT
56#define IMPORT
57#pragma warning Unknown dynamic link import / export semantics.
58#endif
59
60#if defined(RADIOTAP_FAST_UNALIGNED_ACCESS)
61#define get_unaligned(p) \
62 __extension__({ \
63 struct packed_dummy_struct { \
64 typeof(*(p)) __val; \
65 } __attribute__((packed)) *__ptr = (void *) (p); \
66 \
67 __ptr->__val; \
68 })
69#else
70#define get_unaligned(p) \
71 __extension__({ \
72 typeof(*(p)) __tmp; \
73 memmove(&__tmp, (p), sizeof(*(p))); \
74 __tmp; \
75 })
76#endif
77
78#define get_unaligned_le16(p) le16_to_cpu(get_unaligned((uint16_t *) (p)))
79#define get_unaligned_le32(p) le32_to_cpu(get_unaligned((uint32_t *) (p)))
80
81#define UNALIGNED_ADDRESS(x) ((void *) (x))
diff --git a/src/libwifi/core/radiotap/radiotap.c b/src/libwifi/core/radiotap/radiotap.c new file mode 100644 index 0000000..5d46223 --- /dev/null +++ b/src/libwifi/core/radiotap/radiotap.c
@@ -0,0 +1,469 @@
1/*
2 * Radiotap parser
3 *
4 * Copyright 2007 Andy Green <andy@warmcat.com>
5 * Copyright 2009 Johannes Berg <johannes@sipsolutions.net>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * Alternatively, this software may be distributed under the terms of ISC
12 * license, see COPYING for more details.
13 */
14#include "platform.h"
15#include "radiotap_iter.h"
16
17/* function prototypes and related defs are in radiotap_iter.h */
18
19static const struct radiotap_align_size rtap_namespace_sizes[] = {
20 [IEEE80211_RADIOTAP_TSFT] =
21 {
22 .align = 8,
23 .size = 8,
24 },
25 [IEEE80211_RADIOTAP_FLAGS] =
26 {
27 .align = 1,
28 .size = 1,
29 },
30 [IEEE80211_RADIOTAP_RATE] =
31 {
32 .align = 1,
33 .size = 1,
34 },
35 [IEEE80211_RADIOTAP_CHANNEL] =
36 {
37 .align = 2,
38 .size = 4,
39 },
40 [IEEE80211_RADIOTAP_FHSS] =
41 {
42 .align = 2,
43 .size = 2,
44 },
45 [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] =
46 {
47 .align = 1,
48 .size = 1,
49 },
50 [IEEE80211_RADIOTAP_DBM_ANTNOISE] =
51 {
52 .align = 1,
53 .size = 1,
54 },
55 [IEEE80211_RADIOTAP_LOCK_QUALITY] =
56 {
57 .align = 2,
58 .size = 2,
59 },
60 [IEEE80211_RADIOTAP_TX_ATTENUATION] =
61 {
62 .align = 2,
63 .size = 2,
64 },
65 [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] =
66 {
67 .align = 2,
68 .size = 2,
69 },
70 [IEEE80211_RADIOTAP_DBM_TX_POWER] =
71 {
72 .align = 1,
73 .size = 1,
74 },
75 [IEEE80211_RADIOTAP_ANTENNA] =
76 {
77 .align = 1,
78 .size = 1,
79 },
80 [IEEE80211_RADIOTAP_DB_ANTSIGNAL] =
81 {
82 .align = 1,
83 .size = 1,
84 },
85 [IEEE80211_RADIOTAP_DB_ANTNOISE] =
86 {
87 .align = 1,
88 .size = 1,
89 },
90 [IEEE80211_RADIOTAP_RX_FLAGS] =
91 {
92 .align = 2,
93 .size = 2,
94 },
95 [IEEE80211_RADIOTAP_TX_FLAGS] =
96 {
97 .align = 2,
98 .size = 2,
99 },
100 [IEEE80211_RADIOTAP_RTS_RETRIES] =
101 {
102 .align = 1,
103 .size = 1,
104 },
105 [IEEE80211_RADIOTAP_DATA_RETRIES] =
106 {
107 .align = 1,
108 .size = 1,
109 },
110 [IEEE80211_RADIOTAP_MCS] =
111 {
112 .align = 1,
113 .size = 3,
114 },
115 [IEEE80211_RADIOTAP_AMPDU_STATUS] =
116 {
117 .align = 4,
118 .size = 8,
119 },
120 [IEEE80211_RADIOTAP_VHT] =
121 {
122 .align = 2,
123 .size = 12,
124 },
125 [IEEE80211_RADIOTAP_TIMESTAMP] =
126 {
127 .align = 8,
128 .size = 12,
129 },
130 /*
131 * add more here as they are defined in radiotap.h
132 */
133};
134
135const struct ieee80211_radiotap_namespace radiotap_ns = {
136 .n_bits = sizeof(rtap_namespace_sizes) / sizeof(rtap_namespace_sizes[0]),
137 .align_size = rtap_namespace_sizes,
138};
139
140/**
141 * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization
142 * @iterator: radiotap_iterator to initialize
143 * @radiotap_header: radiotap header to parse
144 * @max_length: total length we can parse into (eg, whole packet length)
145 *
146 * Returns: 0 or a negative error code if there is a problem.
147 *
148 * This function initializes an opaque iterator struct which can then
149 * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap
150 * argument which is present in the header. It knows about extended
151 * present headers and handles them.
152 *
153 * How to use:
154 * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator
155 * struct ieee80211_radiotap_iterator (no need to init the struct beforehand)
156 * checking for a good 0 return code. Then loop calling
157 * __ieee80211_radiotap_iterator_next()... it returns either 0,
158 * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem.
159 * The iterator's @this_arg member points to the start of the argument
160 * associated with the current argument index that is present, which can be
161 * found in the iterator's @this_arg_index member. This arg index corresponds
162 * to the IEEE80211_RADIOTAP_... defines.
163 *
164 * Radiotap header length:
165 * You can find the CPU-endian total radiotap header length in
166 * iterator->max_length after executing ieee80211_radiotap_iterator_init()
167 * successfully.
168 *
169 * Alignment Gotcha:
170 * You must take care when dereferencing iterator.this_arg
171 * for multibyte types... the pointer is not aligned. Use
172 * get_unaligned((type *)iterator.this_arg) to dereference
173 * iterator.this_arg for type "type" safely on all arches.
174 *
175 * Example code: parse.c
176 */
177
178EXPORT
179int ieee80211_radiotap_iterator_init(struct ieee80211_radiotap_iterator *iterator,
180 struct ieee80211_radiotap_header *radiotap_header, int max_length,
181 const struct ieee80211_radiotap_vendor_namespaces *vns) {
182 /* must at least have the radiotap header */
183 if (max_length < (int) sizeof(struct ieee80211_radiotap_header))
184 return -EINVAL;
185
186 /* Linux only supports version 0 radiotap format */
187 if (radiotap_header->it_version)
188 return -EINVAL;
189
190 /* sanity check for allowed length and radiotap length field */
191 if (max_length < get_unaligned_le16(UNALIGNED_ADDRESS(&radiotap_header->it_len)))
192 return -EINVAL;
193
194 iterator->_rtheader = radiotap_header;
195 iterator->_max_length = get_unaligned_le16(UNALIGNED_ADDRESS(&radiotap_header->it_len));
196 iterator->_arg_index = 0;
197 iterator->_bitmap_shifter = get_unaligned_le32(UNALIGNED_ADDRESS(&radiotap_header->it_present));
198 iterator->_arg = (uint8_t *) radiotap_header + sizeof(*radiotap_header);
199 iterator->_reset_on_ext = 0;
200#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 9
201#pragma GCC diagnostic push
202#pragma GCC diagnostic ignored "-Waddress-of-packed-member"
203#endif
204 iterator->_next_bitmap = UNALIGNED_ADDRESS(&radiotap_header->it_present);
205#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 9
206#pragma GCC diagnostic pop
207#endif
208 iterator->_next_bitmap++;
209 iterator->_vns = vns;
210 iterator->current_namespace = &radiotap_ns;
211 iterator->is_radiotap_ns = 1;
212#ifdef RADIOTAP_SUPPORT_OVERRIDES
213 iterator->n_overrides = 0;
214 iterator->overrides = NULL;
215#endif
216
217 /* find payload start allowing for extended bitmap(s) */
218
219 if (iterator->_bitmap_shifter & (1 << IEEE80211_RADIOTAP_EXT)) {
220 if ((unsigned long) iterator->_arg - (unsigned long) iterator->_rtheader + sizeof(uint32_t) >
221 (unsigned long) iterator->_max_length)
222 return -EINVAL;
223 while (get_unaligned_le32(iterator->_arg) & (1 << IEEE80211_RADIOTAP_EXT)) {
224 iterator->_arg += sizeof(uint32_t);
225
226 /*
227 * check for insanity where the present bitmaps
228 * keep claiming to extend up to or even beyond the
229 * stated radiotap header length
230 */
231
232 if ((unsigned long) iterator->_arg - (unsigned long) iterator->_rtheader + sizeof(uint32_t) >
233 (unsigned long) iterator->_max_length)
234 return -EINVAL;
235 }
236
237 iterator->_arg += sizeof(uint32_t);
238
239 /*
240 * no need to check again for blowing past stated radiotap
241 * header length, because ieee80211_radiotap_iterator_next
242 * checks it before it is dereferenced
243 */
244 }
245
246 iterator->this_arg = iterator->_arg;
247
248 /* we are all initialized happily */
249
250 return 0;
251}
252
253static void find_ns(struct ieee80211_radiotap_iterator *iterator, uint32_t oui, uint8_t subns) {
254 int i;
255
256 iterator->current_namespace = NULL;
257
258 if (!iterator->_vns)
259 return;
260
261 for (i = 0; i < iterator->_vns->n_ns; i++) {
262 if (iterator->_vns->ns[i].oui != oui)
263 continue;
264 if (iterator->_vns->ns[i].subns != subns)
265 continue;
266
267 iterator->current_namespace = &iterator->_vns->ns[i];
268 break;
269 }
270}
271
272#ifdef RADIOTAP_SUPPORT_OVERRIDES
273static int find_override(struct ieee80211_radiotap_iterator *iterator, int *align, int *size) {
274 int i;
275
276 if (!iterator->overrides)
277 return 0;
278
279 for (i = 0; i < iterator->n_overrides; i++) {
280 if (iterator->_arg_index == iterator->overrides[i].field) {
281 *align = iterator->overrides[i].align;
282 *size = iterator->overrides[i].size;
283 if (!*align) /* erroneous override */
284 return 0;
285 return 1;
286 }
287 }
288
289 return 0;
290}
291#endif
292
293/**
294 * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg
295 * @iterator: radiotap_iterator to move to next arg (if any)
296 *
297 * Returns: 0 if there is an argument to handle,
298 * -ENOENT if there are no more args or -EINVAL
299 * if there is something else wrong.
300 *
301 * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*)
302 * in @this_arg_index and sets @this_arg to point to the
303 * payload for the field. It takes care of alignment handling and extended
304 * present fields. @this_arg can be changed by the caller (eg,
305 * incremented to move inside a compound argument like
306 * IEEE80211_RADIOTAP_CHANNEL). The args pointed to are in
307 * little-endian format whatever the endianness of your CPU.
308 *
309 * Alignment Gotcha:
310 * You must take care when dereferencing iterator.this_arg
311 * for multibyte types... the pointer is not aligned. Use
312 * get_unaligned((type *)iterator.this_arg) to dereference
313 * iterator.this_arg for type "type" safely on all arches.
314 */
315
316EXPORT
317int ieee80211_radiotap_iterator_next(struct ieee80211_radiotap_iterator *iterator) {
318 while (1) {
319 int hit = 0;
320 int pad, align, size, subns;
321 uint32_t oui;
322
323 /* if no more EXT bits, that's it */
324 if ((iterator->_arg_index % 32) == IEEE80211_RADIOTAP_EXT && !(iterator->_bitmap_shifter & 1))
325 return -ENOENT;
326
327 if (!(iterator->_bitmap_shifter & 1))
328 goto next_entry; /* arg not present */
329
330 /* get alignment/size of data */
331 switch (iterator->_arg_index % 32) {
332 case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE:
333 case IEEE80211_RADIOTAP_EXT:
334 align = 1;
335 size = 0;
336 break;
337 case IEEE80211_RADIOTAP_VENDOR_NAMESPACE:
338 align = 2;
339 size = 6;
340 break;
341 default:
342#ifdef RADIOTAP_SUPPORT_OVERRIDES
343 if (find_override(iterator, &align, &size)) {
344 /* all set */
345 } else
346#endif
347 if (!iterator->current_namespace ||
348 iterator->_arg_index >= iterator->current_namespace->n_bits) {
349 if (iterator->current_namespace == &radiotap_ns)
350 return -ENOENT;
351 align = 0;
352 } else {
353 align = iterator->current_namespace->align_size[iterator->_arg_index].align;
354 size = iterator->current_namespace->align_size[iterator->_arg_index].size;
355 }
356 if (!align) {
357 /* skip all subsequent data */
358 iterator->_arg = iterator->_next_ns_data;
359 /* give up on this namespace */
360 iterator->current_namespace = NULL;
361 goto next_entry;
362 }
363 break;
364 }
365
366 /*
367 * arg is present, account for alignment padding
368 *
369 * Note that these alignments are relative to the start
370 * of the radiotap header. There is no guarantee
371 * that the radiotap header itself is aligned on any
372 * kind of boundary.
373 *
374 * The above is why get_unaligned() is used to dereference
375 * multibyte elements from the radiotap area.
376 */
377
378 pad = ((unsigned long) iterator->_arg - (unsigned long) iterator->_rtheader) & (align - 1);
379
380 if (pad)
381 iterator->_arg += align - pad;
382
383 if (iterator->_arg_index % 32 == IEEE80211_RADIOTAP_VENDOR_NAMESPACE) {
384 int vnslen;
385
386 if ((unsigned long) iterator->_arg + size - (unsigned long) iterator->_rtheader >
387 (unsigned long) iterator->_max_length)
388 return -EINVAL;
389
390 oui = (*iterator->_arg << 16) | (*(iterator->_arg + 1) << 8) | *(iterator->_arg + 2);
391 subns = *(iterator->_arg + 3);
392
393 find_ns(iterator, oui, subns);
394
395 vnslen = get_unaligned_le16(iterator->_arg + 4);
396 iterator->_next_ns_data = iterator->_arg + size + vnslen;
397 if (!iterator->current_namespace)
398 size += vnslen;
399 }
400
401 /*
402 * this is what we will return to user, but we need to
403 * move on first so next call has something fresh to test
404 */
405 iterator->this_arg_index = iterator->_arg_index;
406 iterator->this_arg = iterator->_arg;
407 iterator->this_arg_size = size;
408
409 /* internally move on the size of this arg */
410 iterator->_arg += size;
411
412 /*
413 * check for insanity where we are given a bitmap that
414 * claims to have more arg content than the length of the
415 * radiotap section. We will normally end up equalling this
416 * max_length on the last arg, never exceeding it.
417 */
418
419 if ((unsigned long) iterator->_arg - (unsigned long) iterator->_rtheader >
420 (unsigned long) iterator->_max_length)
421 return -EINVAL;
422
423 /* these special ones are valid in each bitmap word */
424 switch (iterator->_arg_index % 32) {
425 case IEEE80211_RADIOTAP_VENDOR_NAMESPACE:
426 iterator->_reset_on_ext = 1;
427
428 iterator->is_radiotap_ns = 0;
429 /*
430 * If parser didn't register this vendor
431 * namespace with us, allow it to show it
432 * as 'raw. Do do that, set argument index
433 * to vendor namespace.
434 */
435 iterator->this_arg_index = IEEE80211_RADIOTAP_VENDOR_NAMESPACE;
436 if (!iterator->current_namespace)
437 hit = 1;
438 goto next_entry;
439 case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE:
440 iterator->_reset_on_ext = 1;
441 iterator->current_namespace = &radiotap_ns;
442 iterator->is_radiotap_ns = 1;
443 goto next_entry;
444 case IEEE80211_RADIOTAP_EXT:
445 /*
446 * bit 31 was set, there is more
447 * -- move to next u32 bitmap
448 */
449 iterator->_bitmap_shifter = get_unaligned_le32(iterator->_next_bitmap);
450 iterator->_next_bitmap++;
451 if (iterator->_reset_on_ext)
452 iterator->_arg_index = 0;
453 else
454 iterator->_arg_index++;
455 iterator->_reset_on_ext = 0;
456 break;
457 default:
458 /* we've got a hit! */
459 hit = 1;
460 next_entry:
461 iterator->_bitmap_shifter >>= 1;
462 iterator->_arg_index++;
463 }
464
465 /* if we found a valid arg earlier, return it now */
466 if (hit)
467 return 0;
468 }
469}
diff --git a/src/libwifi/core/radiotap/radiotap.h b/src/libwifi/core/radiotap/radiotap.h new file mode 100644 index 0000000..cd6dd57 --- /dev/null +++ b/src/libwifi/core/radiotap/radiotap.h
@@ -0,0 +1,221 @@
1/*
2 * Copyright (c) 2017 Intel Deutschland GmbH
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16#ifndef __RADIOTAP_H
17#define __RADIOTAP_H
18
19#if defined(__APPLE__)
20#include <libkern/OSByteOrder.h>
21#define bswap_16 OSSwapInt16
22#define bswap_32 OSSwapInt32
23#define bswap_64 OSSwapInt64
24#include <machine/endian.h>
25#ifndef le16toh
26#define le16toh(x) OSSwapLittleToHostInt16(x)
27#endif
28#ifndef le32toh
29#define le32toh(x) OSSwapLittleToHostInt32(x)
30#endif
31#ifndef le64toh
32#define le64toh(x) OSSwapLittleToHostInt64(x)
33#endif
34#endif
35
36#include <stdint.h>
37
38/**
39 * struct ieee82011_radiotap_header - base radiotap header
40 */
41struct ieee80211_radiotap_header {
42 /**
43 * @it_version: radiotap version, always 0
44 */
45 uint8_t it_version;
46
47 /**
48 * @it_pad: padding (or alignment)
49 */
50 uint8_t it_pad;
51
52 /**
53 * @it_len: overall radiotap header length
54 */
55 uint16_t it_len;
56
57 /**
58 * @it_present: (first) present word
59 */
60 uint32_t it_present;
61} __attribute__((__packed__));
62
63/* version is always 0 */
64#define PKTHDR_RADIOTAP_VERSION 0
65
66extern const struct ieee80211_radiotap_namespace radiotap_ns;
67
68/* see the radiotap website for the descriptions */
69enum ieee80211_radiotap_presence {
70 IEEE80211_RADIOTAP_TSFT = 0,
71 IEEE80211_RADIOTAP_FLAGS = 1,
72 IEEE80211_RADIOTAP_RATE = 2,
73 IEEE80211_RADIOTAP_CHANNEL = 3,
74 IEEE80211_RADIOTAP_FHSS = 4,
75 IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5,
76 IEEE80211_RADIOTAP_DBM_ANTNOISE = 6,
77 IEEE80211_RADIOTAP_LOCK_QUALITY = 7,
78 IEEE80211_RADIOTAP_TX_ATTENUATION = 8,
79 IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9,
80 IEEE80211_RADIOTAP_DBM_TX_POWER = 10,
81 IEEE80211_RADIOTAP_ANTENNA = 11,
82 IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
83 IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
84 IEEE80211_RADIOTAP_RX_FLAGS = 14,
85 IEEE80211_RADIOTAP_TX_FLAGS = 15,
86 IEEE80211_RADIOTAP_RTS_RETRIES = 16,
87 IEEE80211_RADIOTAP_DATA_RETRIES = 17,
88 /* 18 is XChannel, but it's not defined yet */
89 IEEE80211_RADIOTAP_MCS = 19,
90 IEEE80211_RADIOTAP_AMPDU_STATUS = 20,
91 IEEE80211_RADIOTAP_VHT = 21,
92 IEEE80211_RADIOTAP_TIMESTAMP = 22,
93
94 /* valid in every it_present bitmap, even vendor namespaces */
95 IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29,
96 IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30,
97 IEEE80211_RADIOTAP_EXT = 31
98};
99
100/* for IEEE80211_RADIOTAP_FLAGS */
101enum ieee80211_radiotap_flags {
102 IEEE80211_RADIOTAP_F_CFP = 0x01,
103 IEEE80211_RADIOTAP_F_SHORTPRE = 0x02,
104 IEEE80211_RADIOTAP_F_WEP = 0x04,
105 IEEE80211_RADIOTAP_F_FRAG = 0x08,
106 IEEE80211_RADIOTAP_F_FCS = 0x10,
107 IEEE80211_RADIOTAP_F_DATAPAD = 0x20,
108 IEEE80211_RADIOTAP_F_BADFCS = 0x40,
109};
110
111/* for IEEE80211_RADIOTAP_CHANNEL */
112enum ieee80211_radiotap_channel_flags {
113 IEEE80211_CHAN_CCK = 0x0020,
114 IEEE80211_CHAN_OFDM = 0x0040,
115 IEEE80211_CHAN_2GHZ = 0x0080,
116 IEEE80211_CHAN_5GHZ = 0x0100,
117 IEEE80211_CHAN_DYN = 0x0400,
118 IEEE80211_CHAN_HALF = 0x4000,
119 IEEE80211_CHAN_QUARTER = 0x8000,
120};
121
122/* for IEEE80211_RADIOTAP_RX_FLAGS */
123enum ieee80211_radiotap_rx_flags {
124 IEEE80211_RADIOTAP_F_RX_BADPLCP = 0x0002,
125};
126
127/* for IEEE80211_RADIOTAP_TX_FLAGS */
128enum ieee80211_radiotap_tx_flags {
129 IEEE80211_RADIOTAP_F_TX_FAIL = 0x0001,
130 IEEE80211_RADIOTAP_F_TX_CTS = 0x0002,
131 IEEE80211_RADIOTAP_F_TX_RTS = 0x0004,
132 IEEE80211_RADIOTAP_F_TX_NOACK = 0x0008,
133};
134
135/* for IEEE80211_RADIOTAP_MCS "have" flags */
136enum ieee80211_radiotap_mcs_have {
137 IEEE80211_RADIOTAP_MCS_HAVE_BW = 0x01,
138 IEEE80211_RADIOTAP_MCS_HAVE_MCS = 0x02,
139 IEEE80211_RADIOTAP_MCS_HAVE_GI = 0x04,
140 IEEE80211_RADIOTAP_MCS_HAVE_FMT = 0x08,
141 IEEE80211_RADIOTAP_MCS_HAVE_FEC = 0x10,
142 IEEE80211_RADIOTAP_MCS_HAVE_STBC = 0x20,
143};
144
145enum ieee80211_radiotap_mcs_flags {
146 IEEE80211_RADIOTAP_MCS_BW_MASK = 0x03,
147 IEEE80211_RADIOTAP_MCS_BW_20 = 0,
148 IEEE80211_RADIOTAP_MCS_BW_40 = 1,
149 IEEE80211_RADIOTAP_MCS_BW_20L = 2,
150 IEEE80211_RADIOTAP_MCS_BW_20U = 3,
151
152 IEEE80211_RADIOTAP_MCS_SGI = 0x04,
153 IEEE80211_RADIOTAP_MCS_FMT_GF = 0x08,
154 IEEE80211_RADIOTAP_MCS_FEC_LDPC = 0x10,
155 IEEE80211_RADIOTAP_MCS_STBC_MASK = 0x60,
156 IEEE80211_RADIOTAP_MCS_STBC_1 = 1,
157 IEEE80211_RADIOTAP_MCS_STBC_2 = 2,
158 IEEE80211_RADIOTAP_MCS_STBC_3 = 3,
159 IEEE80211_RADIOTAP_MCS_STBC_SHIFT = 5,
160};
161
162/* for IEEE80211_RADIOTAP_AMPDU_STATUS */
163enum ieee80211_radiotap_ampdu_flags {
164 IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN = 0x0001,
165 IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN = 0x0002,
166 IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN = 0x0004,
167 IEEE80211_RADIOTAP_AMPDU_IS_LAST = 0x0008,
168 IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR = 0x0010,
169 IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN = 0x0020,
170};
171
172/* for IEEE80211_RADIOTAP_VHT */
173enum ieee80211_radiotap_vht_known {
174 IEEE80211_RADIOTAP_VHT_KNOWN_STBC = 0x0001,
175 IEEE80211_RADIOTAP_VHT_KNOWN_TXOP_PS_NA = 0x0002,
176 IEEE80211_RADIOTAP_VHT_KNOWN_GI = 0x0004,
177 IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS = 0x0008,
178 IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM = 0x0010,
179 IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED = 0x0020,
180 IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH = 0x0040,
181 IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID = 0x0080,
182 IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID = 0x0100,
183};
184
185enum ieee80211_radiotap_vht_flags {
186 IEEE80211_RADIOTAP_VHT_FLAG_STBC = 0x01,
187 IEEE80211_RADIOTAP_VHT_FLAG_TXOP_PS_NA = 0x02,
188 IEEE80211_RADIOTAP_VHT_FLAG_SGI = 0x04,
189 IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9 = 0x08,
190 IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM = 0x10,
191 IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED = 0x20,
192};
193
194enum ieee80211_radiotap_vht_coding {
195 IEEE80211_RADIOTAP_CODING_LDPC_USER0 = 0x01,
196 IEEE80211_RADIOTAP_CODING_LDPC_USER1 = 0x02,
197 IEEE80211_RADIOTAP_CODING_LDPC_USER2 = 0x04,
198 IEEE80211_RADIOTAP_CODING_LDPC_USER3 = 0x08,
199};
200
201/* for IEEE80211_RADIOTAP_TIMESTAMP */
202enum ieee80211_radiotap_timestamp_unit_spos {
203 IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MASK = 0x000F,
204 IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MS = 0x0000,
205 IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US = 0x0001,
206 IEEE80211_RADIOTAP_TIMESTAMP_UNIT_NS = 0x0003,
207 IEEE80211_RADIOTAP_TIMESTAMP_SPOS_MASK = 0x00F0,
208 IEEE80211_RADIOTAP_TIMESTAMP_SPOS_BEGIN_MDPU = 0x0000,
209 IEEE80211_RADIOTAP_TIMESTAMP_SPOS_PLCP_SIG_ACQ = 0x0010,
210 IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_PPDU = 0x0020,
211 IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_MPDU = 0x0030,
212 IEEE80211_RADIOTAP_TIMESTAMP_SPOS_UNKNOWN = 0x00F0,
213};
214
215enum ieee80211_radiotap_timestamp_flags {
216 IEEE80211_RADIOTAP_TIMESTAMP_FLAG_64BIT = 0x00,
217 IEEE80211_RADIOTAP_TIMESTAMP_FLAG_32BIT = 0x01,
218 IEEE80211_RADIOTAP_TIMESTAMP_FLAG_ACCURACY = 0x02,
219};
220
221#endif /* __RADIOTAP_H */
diff --git a/src/libwifi/core/radiotap/radiotap_iter.h b/src/libwifi/core/radiotap/radiotap_iter.h new file mode 100644 index 0000000..5495a64 --- /dev/null +++ b/src/libwifi/core/radiotap/radiotap_iter.h
@@ -0,0 +1,101 @@
1#ifndef __RADIOTAP_ITER_H
2#define __RADIOTAP_ITER_H
3
4#include "platform.h"
5#include "radiotap.h"
6#include <stdint.h>
7
8/* Radiotap header iteration
9 * implemented in radiotap.c
10 */
11
12struct radiotap_override {
13 uint8_t field;
14 uint8_t align : 4, size : 4;
15};
16
17struct radiotap_align_size {
18 uint8_t align : 4, size : 4;
19};
20
21struct ieee80211_radiotap_namespace {
22 const struct radiotap_align_size *align_size;
23 int n_bits;
24 uint32_t oui;
25 uint8_t subns;
26};
27
28struct ieee80211_radiotap_vendor_namespaces {
29 const struct ieee80211_radiotap_namespace *ns;
30 int n_ns;
31};
32
33/**
34 * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args
35 * @this_arg_index: index of current arg, valid after each successful call
36 * to ieee80211_radiotap_iterator_next()
37 * @this_arg: pointer to current radiotap arg; it is valid after each
38 * call to ieee80211_radiotap_iterator_next() but also after
39 * ieee80211_radiotap_iterator_init() where it will point to
40 * the beginning of the actual data portion
41 * @this_arg_size: length of the current arg, for convenience
42 * @current_namespace: pointer to the current namespace definition
43 * (or internally %NULL if the current namespace is unknown)
44 * @is_radiotap_ns: indicates whether the current namespace is the default
45 * radiotap namespace or not
46 *
47 * @overrides: override standard radiotap fields
48 * @n_overrides: number of overrides
49 *
50 * @_rtheader: pointer to the radiotap header we are walking through
51 * @_max_length: length of radiotap header in cpu byte ordering
52 * @_arg_index: next argument index
53 * @_arg: next argument pointer
54 * @_next_bitmap: internal pointer to next present u32
55 * @_bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present
56 * @_vns: vendor namespace definitions
57 * @_next_ns_data: beginning of the next namespace's data
58 * @_reset_on_ext: internal; reset the arg index to 0 when going to the
59 * next bitmap word
60 *
61 * Describes the radiotap parser state. Fields prefixed with an underscore
62 * must not be used by users of the parser, only by the parser internally.
63 */
64
65struct ieee80211_radiotap_iterator {
66 struct ieee80211_radiotap_header *_rtheader;
67 const struct ieee80211_radiotap_vendor_namespaces *_vns;
68 const struct ieee80211_radiotap_namespace *current_namespace;
69
70 unsigned char *_arg, *_next_ns_data;
71 uint32_t *_next_bitmap;
72
73 unsigned char *this_arg;
74 const struct radiotap_override *overrides; /* Only for RADIOTAP_SUPPORT_OVERRIDES */
75 int n_overrides; /* Only for RADIOTAP_SUPPORT_OVERRIDES */
76 int this_arg_index;
77 int this_arg_size;
78
79 int is_radiotap_ns;
80
81 int _max_length;
82 int _arg_index;
83 uint32_t _bitmap_shifter;
84 int _reset_on_ext;
85};
86
87#ifdef __cplusplus
88#define CALLING_CONVENTION "C"
89#else
90#define CALLING_CONVENTION
91#endif
92
93IMPORT extern CALLING_CONVENTION int
94ieee80211_radiotap_iterator_init(struct ieee80211_radiotap_iterator *iterator,
95 struct ieee80211_radiotap_header *radiotap_header, int max_length,
96 const struct ieee80211_radiotap_vendor_namespaces *vns);
97
98IMPORT extern CALLING_CONVENTION int
99ieee80211_radiotap_iterator_next(struct ieee80211_radiotap_iterator *iterator);
100
101#endif /* __RADIOTAP_ITER_H */
diff --git a/src/libwifi/gen/control/cts.c b/src/libwifi/gen/control/cts.c new file mode 100644 index 0000000..f0e4df8 --- /dev/null +++ b/src/libwifi/gen/control/cts.c
@@ -0,0 +1,30 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "cts.h"
17
18#include <string.h>
19
20int libwifi_create_cts(struct libwifi_cts *cts, const unsigned char receiver[6], uint16_t duration) {
21 memset(cts, 0, sizeof(struct libwifi_cts));
22
23 cts->frame_header.frame_control.type = TYPE_CONTROL;
24 cts->frame_header.frame_control.subtype = SUBTYPE_CTS;
25 cts->frame_header.duration = duration;
26
27 memcpy(cts->receiver_addr, receiver, 6);
28
29 return 0;
30}
diff --git a/src/libwifi/gen/control/cts.h b/src/libwifi/gen/control/cts.h new file mode 100644 index 0000000..bd31d33 --- /dev/null +++ b/src/libwifi/gen/control/cts.h
@@ -0,0 +1,30 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_GEN_CTS_H
17#define LIBWIFI_GEN_CTS_H
18
19#include "../../core/frame/control/cts.h"
20
21/**
22 * Create a CTS Control frame
23 *
24 * @param cts A fresh libwifi_cts struct
25 * @param receiver The receiver MAC address
26 * @param duration The duration of the clear-to-send
27 */
28int libwifi_create_cts(struct libwifi_cts *cts, const unsigned char receiver[6], uint16_t duration);
29
30#endif /* LIBWIFI_GEN_CTS_H */
diff --git a/src/libwifi/gen/control/rts.c b/src/libwifi/gen/control/rts.c new file mode 100644 index 0000000..e1710f9 --- /dev/null +++ b/src/libwifi/gen/control/rts.c
@@ -0,0 +1,32 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "rts.h"
17
18#include <string.h>
19
20int libwifi_create_rts(struct libwifi_rts *rts, const unsigned char transmitter[6],
21 const unsigned char receiver[6], uint16_t duration) {
22 memset(rts, 0, sizeof(struct libwifi_rts));
23
24 rts->frame_header.frame_control.type = TYPE_CONTROL;
25 rts->frame_header.frame_control.subtype = SUBTYPE_RTS;
26 rts->frame_header.duration = duration;
27
28 memcpy(rts->transmitter_addr, transmitter, 6);
29 memcpy(rts->receiver_addr, receiver, 6);
30
31 return 0;
32}
diff --git a/src/libwifi/gen/control/rts.h b/src/libwifi/gen/control/rts.h new file mode 100644 index 0000000..4ad0bae --- /dev/null +++ b/src/libwifi/gen/control/rts.h
@@ -0,0 +1,32 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_GEN_RTS_H
17#define LIBWIFI_GEN_RTS_H
18
19#include "../../core/frame/control/rts.h"
20
21/**
22 * Create a RTS Control frame
23 *
24 * @param rts A fresh libwifi_rts struct
25 * @param transmitter The transmitter MAC address
26 * @param receiver The receiver MAC address
27 * @param duration The duration of the clear-to-send
28 */
29int libwifi_create_rts(struct libwifi_rts *rts, const unsigned char transmitter[6],
30 const unsigned char receiver[6], uint16_t duration);
31
32#endif /* LIBWIFI_GEN_RTS_H */
diff --git a/src/libwifi/gen/management/action.c b/src/libwifi/gen/management/action.c new file mode 100644 index 0000000..04d7a5f --- /dev/null +++ b/src/libwifi/gen/management/action.c
@@ -0,0 +1,110 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "action.h"
17
18#include <errno.h>
19#include <stdlib.h>
20#include <string.h>
21
22size_t libwifi_add_action_detail(struct libwifi_action_detail *detail, const unsigned char *data,
23 size_t data_len) {
24 if (detail->detail_length != 0) {
25 detail->detail = realloc(detail->detail, data_len);
26 } else {
27 detail->detail = malloc(data_len);
28 }
29
30 if (detail->detail == NULL) {
31 return -EINVAL;
32 }
33
34 detail->detail_length = data_len;
35
36 memcpy(detail->detail, data, data_len);
37 detail->detail_length = data_len;
38
39 return detail->detail_length;
40}
41
42void libwifi_free_action_detail(struct libwifi_action_detail *detail) {
43 if (detail->detail_length != 0) {
44 free(detail->detail);
45 detail->detail_length = 0;
46 }
47}
48
49int libwifi_create_action(struct libwifi_action *action, const unsigned char receiver[6],
50 const unsigned char transmitter[6], uint8_t category) {
51 memset(action, 0, sizeof(struct libwifi_action));
52
53 action->frame_header.frame_control.type = TYPE_MANAGEMENT;
54 action->frame_header.frame_control.subtype = SUBTYPE_ACTION;
55 memcpy(&action->frame_header.addr1, receiver, 6);
56 memcpy(&action->frame_header.addr2, transmitter, 6);
57 memcpy(&action->frame_header.addr3, transmitter, 6);
58
59 action->frame_header.seq_control.sequence_number = (rand() % 4096);
60
61 action->fixed_parameters.category = category;
62
63 return 0;
64}
65
66int libwifi_create_action_no_ack(struct libwifi_action *action, const unsigned char receiver[6],
67 const unsigned char transmitter[6], uint8_t category) {
68 memset(action, 0, sizeof(struct libwifi_action));
69
70 action->frame_header.frame_control.type = TYPE_MANAGEMENT;
71 action->frame_header.frame_control.subtype = SUBTYPE_ACTION_NOACK;
72 memcpy(&action->frame_header.addr1, receiver, 6);
73 memcpy(&action->frame_header.addr2, transmitter, 6);
74 memcpy(&action->frame_header.addr3, transmitter, 6);
75
76 action->frame_header.seq_control.sequence_number = (rand() % 4096);
77
78 action->fixed_parameters.category = category;
79
80 return 0;
81}
82
83size_t libwifi_get_action_length(struct libwifi_action *action) {
84 return sizeof(struct libwifi_mgmt_unordered_frame_header) + sizeof(action->fixed_parameters.category) +
85 action->fixed_parameters.details.detail_length;
86}
87
88size_t libwifi_dump_action(struct libwifi_action *action, unsigned char *buf, size_t buf_len) {
89 size_t action_len = libwifi_get_action_length(action);
90 if (action_len > buf_len) {
91 return -EINVAL;
92 }
93
94 size_t offset = 0;
95
96 memcpy(buf + offset, &action->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header));
97 offset += sizeof(struct libwifi_mgmt_unordered_frame_header);
98
99 memcpy(buf + offset, &action->fixed_parameters.category, sizeof(action->fixed_parameters.category));
100 offset += sizeof(action->fixed_parameters.category);
101 memcpy(buf + offset, action->fixed_parameters.details.detail,
102 action->fixed_parameters.details.detail_length);
103 offset += action->fixed_parameters.details.detail_length;
104
105 return action_len;
106}
107
108void libwifi_free_action(struct libwifi_action *action) {
109 free(action->fixed_parameters.details.detail);
110}
diff --git a/src/libwifi/gen/management/action.h b/src/libwifi/gen/management/action.h new file mode 100644 index 0000000..ae1b5cc --- /dev/null +++ b/src/libwifi/gen/management/action.h
@@ -0,0 +1,80 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_GEN_ACTION_H
17#define LIBWIFI_GEN_ACTION_H
18
19#include "../../core/frame/management/action.h"
20#include <stdint.h>
21
22/**
23 * Create a detail for an action frame by supplying raw data and it's length.
24 * New data can be added to an existing libwifi_action_detail.
25 *
26 * @param detail A libwifi_action_detail struct
27 * @param data Raw data to be added to the libwifi_action_detail
28 * @param data_len Length of the raw data
29 * @return Length of the action
30 */
31size_t libwifi_add_action_detail(struct libwifi_action_detail *detail, const unsigned char *data,
32 size_t data_len);
33
34/**
35 * Free all memory in a given libwifi_action_detail.
36 *
37 * @param detail A used libwifi_action_detail struct
38 */
39void libwifi_free_action_detail(struct libwifi_action_detail *detail);
40
41/**
42 * Create a new action frame with a specified action and category.
43 *
44 * @param action A new libwifi_action struct
45 * @param receiver The receiver MAC address
46 * @param transmitter The transmitter MAC address
47 * @param category The action frame category
48 * @return zero on success
49 */
50int libwifi_create_action(struct libwifi_action *action, const unsigned char receiver[6],
51 const unsigned char transmitter[6], uint8_t category);
52int libwifi_create_action_no_ack(struct libwifi_action *action, const unsigned char receiver[6],
53 const unsigned char transmitter[6], uint8_t category);
54
55/**
56 * Get the length of a given libwifi_action
57 *
58 * @param action A used libwifi_action struct
59 * @return The length of the given libwifi_action
60 */
61size_t libwifi_get_action_length(struct libwifi_action *action);
62
63/**
64 * Dump a given libwifi_action to a raw buffer
65 *
66 * @param action A used libwifi_action struct
67 * @param buf A buffer receiver
68 * @param buf_len The length of the given buf
69 * @return Bytes written to the buf
70 */
71size_t libwifi_dump_action(struct libwifi_action *action, unsigned char *buf, size_t buf_len);
72
73/**
74 * Free data associated to a given libwifi_action
75 *
76 * @param action A used libwifi_action struct
77 */
78void libwifi_free_action(struct libwifi_action *action);
79
80#endif /* LIBWIFI_GEN_ACTION_H */
diff --git a/src/libwifi/gen/management/assoc_request.c b/src/libwifi/gen/management/assoc_request.c new file mode 100644 index 0000000..8ba3585 --- /dev/null +++ b/src/libwifi/gen/management/assoc_request.c
@@ -0,0 +1,85 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "assoc_request.h"
17#include "common.h"
18
19#include <errno.h>
20#include <stdlib.h>
21#include <string.h>
22
23/**
24 * The length of an association request frame is the sum of the header length, the fixed parameters length,
25 * and the tagged parameters length.
26 */
27size_t libwifi_get_assoc_req_length(struct libwifi_assoc_req *assoc_req) {
28 return sizeof(assoc_req->frame_header) + sizeof(struct libwifi_assoc_req_fixed_parameters) +
29 assoc_req->tags.length;
30}
31
32/**
33 * The generated association request frame is made with sane defaults defined in common.h.
34 * Two tagged parameters are also added to the association request: SSID and Channel.
35 */
36int libwifi_create_assoc_req(struct libwifi_assoc_req *assoc_req, const unsigned char receiver[6],
37 const unsigned char transmitter[6], const char *ssid, uint8_t channel) {
38 memset(assoc_req, 0, sizeof(struct libwifi_assoc_req));
39
40 assoc_req->frame_header.frame_control.type = TYPE_MANAGEMENT;
41 assoc_req->frame_header.frame_control.subtype = SUBTYPE_ASSOC_REQ;
42 memcpy(&assoc_req->frame_header.addr1, receiver, 6);
43 memcpy(&assoc_req->frame_header.addr2, transmitter, 6);
44 memcpy(&assoc_req->frame_header.addr3, receiver, 6);
45 assoc_req->frame_header.seq_control.sequence_number = (rand() % 4096);
46
47 assoc_req->fixed_parameters.capabilities_information = BYTESWAP16(LIBWIFI_DEFAULT_AP_CAPABS);
48 assoc_req->fixed_parameters.listen_interval = BYTESWAP16(LIBWIFI_DEFAULT_LISTEN_INTERVAL);
49
50 libwifi_quick_add_tag(&assoc_req->tags, TAG_SSID, (const unsigned char *) ssid, strlen(ssid));
51 libwifi_quick_add_tag(&assoc_req->tags, TAG_DS_PARAMETER, (const unsigned char *) &channel, 1);
52
53 return 0;
54}
55
56/**
57 * Copy a libwifi_assoc_req into a regular unsigned char buffer. This is useful when injecting generated
58 * libwifi frames.
59 */
60size_t libwifi_dump_assoc_req(struct libwifi_assoc_req *assoc_req, unsigned char *buf, size_t buf_len) {
61 size_t assoc_req_len = libwifi_get_assoc_req_length(assoc_req);
62 if (assoc_req_len > buf_len) {
63 return -EINVAL;
64 }
65
66 size_t offset = 0;
67 memcpy(buf + offset, &assoc_req->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header));
68 offset += sizeof(struct libwifi_mgmt_unordered_frame_header);
69
70 memcpy(buf + offset, &assoc_req->fixed_parameters, sizeof(struct libwifi_assoc_req_fixed_parameters));
71 offset += sizeof(struct libwifi_assoc_req_fixed_parameters);
72
73 memcpy(buf + offset, assoc_req->tags.parameters, assoc_req->tags.length);
74 offset += assoc_req->tags.length;
75
76 return assoc_req_len;
77}
78
79/**
80 * Because the tagged parameters memory is managed inside of the library, the library must
81 * be the one to free it, too.
82 */
83void libwifi_free_assoc_req(struct libwifi_assoc_req *assoc_req) {
84 free(assoc_req->tags.parameters);
85}
diff --git a/src/libwifi/gen/management/assoc_request.h b/src/libwifi/gen/management/assoc_request.h new file mode 100644 index 0000000..85cbd3b --- /dev/null +++ b/src/libwifi/gen/management/assoc_request.h
@@ -0,0 +1,39 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_GEN_ASSOCREQUEST_H
17#define LIBWIFI_GEN_ASSOCREQUEST_H
18
19#include "../../core/frame/frame.h"
20#include "../../core/frame/management/assoc_request.h"
21#include "../../core/frame/management/common.h"
22
23/**
24 * Create a new association request
25 *
26 * @param assoc_req A new libwifi_assoc_req struct
27 * @param receiver The receiver MAC address
28 * @param transmitter The transmitter MAC address
29 * @param ssid The desired BSS SSID
30 * @param channel The desired channel
31 * @param zero on success
32 */
33int libwifi_create_assoc_req(struct libwifi_assoc_req *assoc_req, const unsigned char receiver[6],
34 const unsigned char transmitter[6], const char *ssid, uint8_t channel);
35size_t libwifi_get_assoc_req_length(struct libwifi_assoc_req *assoc_req);
36size_t libwifi_dump_assoc_req(struct libwifi_assoc_req *assoc_req, unsigned char *buf, size_t buf_len);
37void libwifi_free_assoc_req(struct libwifi_assoc_req *assoc_req);
38
39#endif /* LIBWIFI_GEN_ASSOCREQUEST_H */
diff --git a/src/libwifi/gen/management/assoc_response.c b/src/libwifi/gen/management/assoc_response.c new file mode 100644 index 0000000..be00511 --- /dev/null +++ b/src/libwifi/gen/management/assoc_response.c
@@ -0,0 +1,106 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "assoc_response.h"
17#include "../../core/frame/tag.h"
18#include "../../core/frame/tag_iterator.h"
19#include "../../core/misc/byteswap.h"
20#include "../../core/misc/epoch.h"
21#include "../../core/misc/types.h"
22#include "common.h"
23
24#include <errno.h>
25#include <stdint.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <sys/types.h>
30
31/**
32 * The length of an association response frame is the sum of the header length, the fixed parameters length,
33 * and the tagged parameters length.
34 */
35size_t libwifi_get_assoc_resp_length(struct libwifi_assoc_resp *assoc_resp) {
36 return sizeof(struct libwifi_mgmt_unordered_frame_header) +
37 sizeof(struct libwifi_assoc_resp_fixed_parameters) + assoc_resp->tags.length;
38}
39
40/**
41 * Simple helper function to set the channel of an association response by removing and re-adding the
42 * DS tagged parameter.
43 */
44void libwifi_set_assoc_resp_channel(struct libwifi_assoc_resp *assoc_resp, uint8_t channel) {
45 if (assoc_resp->tags.length != 0) {
46 libwifi_remove_tag(&assoc_resp->tags, TAG_DS_PARAMETER);
47 }
48
49 const unsigned char *chan = (const unsigned char *) &channel;
50
51 libwifi_quick_add_tag(&assoc_resp->tags, TAG_DS_PARAMETER, chan, 1);
52}
53
54/**
55 * The generated association response frame is made with sane defaults defined in common.h and core/types.h.
56 * Two tagged parameters are also added to the association response: Channel and Supported Rates.
57 */
58void libwifi_create_assoc_resp(struct libwifi_assoc_resp *assoc_resp, const unsigned char receiver[6],
59 const unsigned char transmitter[6], uint8_t channel) {
60 memset(assoc_resp, 0, sizeof(struct libwifi_assoc_resp));
61
62 assoc_resp->frame_header.frame_control.type = TYPE_MANAGEMENT;
63 assoc_resp->frame_header.frame_control.subtype = SUBTYPE_ASSOC_RESP;
64 memcpy(&assoc_resp->frame_header.addr1, receiver, 6);
65 memcpy(&assoc_resp->frame_header.addr2, transmitter, 6);
66
67 assoc_resp->fixed_parameters.capabilities_information = BYTESWAP16(LIBWIFI_DEFAULT_AP_CAPABS);
68 assoc_resp->fixed_parameters.status_code = STATUS_SUCCESS;
69 assoc_resp->fixed_parameters.association_id = rand() % 4096;
70
71 libwifi_set_assoc_resp_channel(assoc_resp, channel);
72
73 const unsigned char supported_rates[] = LIBWIFI_DEFAULT_SUPP_RATES;
74 libwifi_quick_add_tag(&assoc_resp->tags, TAG_SUPP_RATES, supported_rates, sizeof(supported_rates) - 1);
75}
76
77/**
78 * Copy a libwifi_assoc_resp into a regular unsigned char buffer. This is useful when injecting generated
79 * libwifi frames.
80 */
81size_t libwifi_dump_assoc_resp(struct libwifi_assoc_resp *assoc_resp, unsigned char *buf, size_t buf_len) {
82 size_t assoc_resp_len = libwifi_get_assoc_resp_length(assoc_resp);
83 if (assoc_resp_len > buf_len) {
84 return -EINVAL;
85 }
86
87 size_t offset = 0;
88 memcpy(buf + offset, &assoc_resp->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header));
89 offset += sizeof(struct libwifi_mgmt_unordered_frame_header);
90
91 memcpy(buf + offset, &assoc_resp->fixed_parameters, sizeof(struct libwifi_assoc_resp_fixed_parameters));
92 offset += sizeof(struct libwifi_assoc_resp_fixed_parameters);
93
94 memcpy(buf + offset, assoc_resp->tags.parameters, assoc_resp->tags.length);
95 offset += assoc_resp->tags.length;
96
97 return assoc_resp_len;
98}
99
100/**
101 * Because the tagged parameters memory is managed inside of the library, the library must
102 * be the one to free it, too.
103 */
104void libwifi_free_assoc_resp(struct libwifi_assoc_resp *assoc_resp) {
105 free(assoc_resp->tags.parameters);
106}
diff --git a/src/libwifi/gen/management/assoc_response.h b/src/libwifi/gen/management/assoc_response.h new file mode 100644 index 0000000..9162d1c --- /dev/null +++ b/src/libwifi/gen/management/assoc_response.h
@@ -0,0 +1,69 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_GEN_ASSOCRESP_H
17#define LIBWIFI_GEN_ASSOCRESP_H
18
19#include "../../core/frame/management/assoc_response.h"
20
21/**
22 * Set the channel of a libwifi_assoc_resp.
23 *
24 * @param assoc_resp A libwifi_assoc_resp
25 * @param channel The new channel
26 */
27void libwifi_set_assoc_resp_channel(struct libwifi_assoc_resp *assoc_resp, uint8_t channel);
28
29/**
30 * Calculate the length of a given libwifi_assoc_resp
31 *
32 * @param assoc_resp A libwifi_assoc_resp
33 * @return The length of the given assoc_resp
34 */
35size_t libwifi_get_assoc_resp_length(struct libwifi_assoc_resp *assoc_resp);
36
37/**
38 * Generate a populated libwifi assoc_resp.
39 *
40 * A generated libwifi assoc_resp can be "dumped" into a buffer for packet injection
41 * via the libwifi_dump_assoc_resp.
42 *
43 * @param assoc_resp A libwifi_assoc_resp
44 * @param receiver The receiver MAC address, aka address 1
45 * @param transmitter The source MAC address, aka address 2
46 * @param channel The desired channel of the assoc_resp
47 *
48 */
49void libwifi_create_assoc_resp(struct libwifi_assoc_resp *assoc_resp, const unsigned char receiver[6],
50 const unsigned char transmitter[6], uint8_t channel);
51
52/**
53 * Dump a libwifi_assoc_resp into a raw format for packet injection.
54 *
55 * @param assoc_resp A libwifi_assoc_resp
56 * @param buf The output buffer for the frame data
57 * @param buf_len The length of the output buffer
58 * @return The length of the dumped assoc_resp
59 */
60size_t libwifi_dump_assoc_resp(struct libwifi_assoc_resp *assoc_resp, unsigned char *buf, size_t buf_len);
61
62/**
63 * Free any memory claimed by a libwifi_assoc_resp back to the system.
64 *
65 * @param assoc_resp A libwifi_assoc_resp
66 */
67void libwifi_free_assoc_resp(struct libwifi_assoc_resp *assoc_resp);
68
69#endif /* LIBWIFI_GEN_ASSOCRESP_H */
diff --git a/src/libwifi/gen/management/atim.c b/src/libwifi/gen/management/atim.c new file mode 100644 index 0000000..960a2de --- /dev/null +++ b/src/libwifi/gen/management/atim.c
@@ -0,0 +1,35 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "atim.h"
17
18#include <stdlib.h>
19#include <string.h>
20
21int libwifi_create_atim(struct libwifi_atim *atim, const unsigned char transmitter[6],
22 const unsigned char receiver[6], const unsigned char bssid[6]) {
23 memset(atim, 0, sizeof(struct libwifi_atim));
24
25 atim->frame_header.frame_control.type = TYPE_MANAGEMENT;
26 atim->frame_header.frame_control.subtype = SUBTYPE_ATIM;
27 memcpy(&atim->frame_header.addr1, transmitter, 6);
28 memcpy(&atim->frame_header.addr2, receiver, 6);
29 memcpy(&atim->frame_header.addr3, bssid, 6);
30 atim->frame_header.frame_control.flags.power_mgmt = 1;
31 atim->frame_header.duration = (rand() % 4096);
32 atim->frame_header.seq_control.sequence_number = (rand() % 4096);
33
34 return 0;
35}
diff --git a/src/libwifi/gen/management/atim.h b/src/libwifi/gen/management/atim.h new file mode 100644 index 0000000..d9a306a --- /dev/null +++ b/src/libwifi/gen/management/atim.h
@@ -0,0 +1,24 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_GEN_ATIM_H
17#define LIBWIFI_GEN_ATIM_H
18
19#include "../../core/frame/management/atim.h"
20
21int libwifi_create_atim(struct libwifi_atim *atim, const unsigned char transmitter[6],
22 const unsigned char receiver[6], const unsigned char bssid[6]);
23
24#endif /* LIBWIFI_GEN_ATIM_H */
diff --git a/src/libwifi/gen/management/authentication.c b/src/libwifi/gen/management/authentication.c new file mode 100644 index 0000000..7fcaa22 --- /dev/null +++ b/src/libwifi/gen/management/authentication.c
@@ -0,0 +1,81 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "authentication.h"
17#include "../../core/misc/byteswap.h"
18
19#include <errno.h>
20#include <stdlib.h>
21#include <string.h>
22
23/**
24 * The length of an authentication frame is the sum of the header length, the fixed parameters length, and the
25 * tagged parameters length.
26 */
27size_t libwifi_get_auth_length(struct libwifi_auth *auth) {
28 return sizeof(struct libwifi_mgmt_unordered_frame_header) + sizeof(struct libwifi_auth_fixed_parameters) +
29 auth->tags.length;
30}
31
32/**
33 * The generated authentication frame is made with sane defaults defined in common.h.
34 */
35void libwifi_create_auth(struct libwifi_auth *auth, const unsigned char receiver[6],
36 const unsigned char transmitter[6], uint16_t algorithm_number,
37 uint16_t transaction_sequence, uint16_t status_code) {
38 memset(auth, 0, sizeof(struct libwifi_auth));
39
40 auth->frame_header.frame_control.type = TYPE_MANAGEMENT;
41 auth->frame_header.frame_control.subtype = SUBTYPE_AUTH;
42 memcpy(&auth->frame_header.addr1, receiver, 6);
43 memcpy(&auth->frame_header.addr2, transmitter, 6);
44 memcpy(&auth->frame_header.addr3, transmitter, 6);
45 auth->frame_header.seq_control.sequence_number = (rand() % 4096);
46
47 auth->fixed_parameters.algorithm_number = algorithm_number;
48 auth->fixed_parameters.transaction_sequence = transaction_sequence;
49 auth->fixed_parameters.status_code = status_code;
50}
51
52/**
53 * Copy a libwifi_auth into a regular unsigned char buffer. This is useful when injecting generated
54 * libwifi frames.
55 */
56size_t libwifi_dump_auth(struct libwifi_auth *auth, unsigned char *buf, size_t buf_len) {
57 size_t auth_len = libwifi_get_auth_length(auth);
58 if (auth_len > buf_len) {
59 return -EINVAL;
60 }
61
62 size_t offset = 0;
63 memcpy(buf + offset, &auth->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header));
64 offset += sizeof(struct libwifi_mgmt_unordered_frame_header);
65
66 memcpy(buf + offset, &auth->fixed_parameters, sizeof(struct libwifi_auth_fixed_parameters));
67 offset += sizeof(struct libwifi_auth_fixed_parameters);
68
69 memcpy(buf + offset, auth->tags.parameters, auth->tags.length);
70 offset += auth->tags.length;
71
72 return auth_len;
73}
74
75/**
76 * Because the tagged parameters memory is managed inside of the library, the library must
77 * be the one to free it, too.
78 */
79void libwifi_free_auth(struct libwifi_auth *auth) {
80 free(auth->tags.parameters);
81}
diff --git a/src/libwifi/gen/management/authentication.h b/src/libwifi/gen/management/authentication.h new file mode 100644 index 0000000..4328f95 --- /dev/null +++ b/src/libwifi/gen/management/authentication.h
@@ -0,0 +1,64 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_GEN_AUTH_H
17#define LIBWIFI_GEN_AUTH_H
18
19#include <stdint.h>
20
21#include "../../core/frame/management/authentication.h"
22
23/**
24 * Calculate the length of a given libwifi_auth
25 *
26 * @param auth A libwifi_auth
27 * @return The length of the given auth
28 */
29size_t libwifi_get_auth_length(struct libwifi_auth *auth);
30
31/**
32 * Generate a populated libwifi auth.
33 *
34 * A generated libwifi auth can be "dumped" into a buffer for packet injection
35 * via the libwifi_dump_auth.
36 *
37 * @param auth A libwifi_auth
38 * @param receiver The receiver MAC address, aka address 1
39 * @param transmitter The source MAC address, aka address 2
40 * @param algorithm_number Algorithm type to use
41 *
42 */
43void libwifi_create_auth(struct libwifi_auth *auth, const unsigned char receiver[6],
44 const unsigned char transmitter[6], uint16_t algorithm_number,
45 uint16_t transaction_sequence, uint16_t status_code);
46
47/**
48 * Dump a libwifi_auth into a raw format for packet injection.
49 *
50 * @param auth A libwifi_auth
51 * @param buf The output buffer for the frame data
52 * @param buf_len The length of the output buffer
53 * @return The length of the dumped auth
54 */
55size_t libwifi_dump_auth(struct libwifi_auth *auth, unsigned char *buf, size_t buf_len);
56
57/**
58 * Free any memory claimed by a libwifi_auth back to the system.
59 *
60 * @param auth A libwifi_auth
61 */
62void libwifi_free_auth(struct libwifi_auth *auth);
63
64#endif /* LIBWIFI_GEN_AUTH_H */
diff --git a/src/libwifi/gen/management/beacon.c b/src/libwifi/gen/management/beacon.c new file mode 100644 index 0000000..4eb394a --- /dev/null +++ b/src/libwifi/gen/management/beacon.c
@@ -0,0 +1,117 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "beacon.h"
17#include "../../core/frame/tag.h"
18#include "../../core/frame/tag_iterator.h"
19#include "../../core/misc/byteswap.h"
20#include "../../core/misc/epoch.h"
21#include "common.h"
22
23#include <errno.h>
24#include <stdint.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <sys/types.h>
29
30/**
31 * The length of a beacon frame is the sum of the header length, the fixed parameters length, and the tagged
32 * parameters length.
33 */
34size_t libwifi_get_beacon_length(struct libwifi_beacon *beacon) {
35 return sizeof(struct libwifi_mgmt_unordered_frame_header) +
36 sizeof(struct libwifi_beacon_fixed_parameters) + beacon->tags.length;
37}
38
39/**
40 * Simple helper to set the beacon SSID tag by removing it and then adding it back with the new value.
41 */
42void libwifi_set_beacon_ssid(struct libwifi_beacon *beacon, const char *ssid) {
43 if (beacon->tags.length != 0) {
44 libwifi_remove_tag(&beacon->tags, TAG_SSID);
45 }
46
47 libwifi_quick_add_tag(&beacon->tags, TAG_SSID, (void *) ssid, strlen(ssid));
48}
49
50/**
51 * Simple helper to set the beacon DS tag by removing it and then adding it back with the new value.
52 */
53void libwifi_set_beacon_channel(struct libwifi_beacon *beacon, uint8_t channel) {
54 if (beacon->tags.length != 0) {
55 libwifi_remove_tag(&beacon->tags, TAG_DS_PARAMETER);
56 }
57
58 const unsigned char *chan = (const unsigned char *) &channel;
59
60 libwifi_quick_add_tag(&beacon->tags, TAG_DS_PARAMETER, chan, 1);
61}
62
63/**
64 * The generated beacon frame is made with sane defaults defined in common.h.
65 * Three tagged parameters are also added to the beacon: SSID, Channel and Supported Rates.
66 */
67void libwifi_create_beacon(struct libwifi_beacon *beacon, const unsigned char receiver[6],
68 const unsigned char transmitter[6], const char *ssid, uint8_t channel) {
69 memset(beacon, 0, sizeof(struct libwifi_beacon));
70
71 beacon->frame_header.frame_control.type = TYPE_MANAGEMENT;
72 beacon->frame_header.frame_control.subtype = SUBTYPE_BEACON;
73 memcpy(&beacon->frame_header.addr1, receiver, 6);
74 memcpy(&beacon->frame_header.addr2, transmitter, 6);
75 beacon->frame_header.seq_control.sequence_number = (rand() % 4096);
76
77 beacon->fixed_parameters.timestamp = BYTESWAP64(libwifi_get_epoch());
78 beacon->fixed_parameters.beacon_interval = BYTESWAP16(LIBWIFI_DEFAULT_BEACON_INTERVAL);
79 beacon->fixed_parameters.capabilities_information = BYTESWAP16(LIBWIFI_DEFAULT_AP_CAPABS);
80
81 libwifi_set_beacon_ssid(beacon, ssid);
82 libwifi_set_beacon_channel(beacon, channel);
83
84 const unsigned char supported_rates[] = LIBWIFI_DEFAULT_SUPP_RATES;
85 libwifi_quick_add_tag(&beacon->tags, TAG_SUPP_RATES, supported_rates, sizeof(supported_rates) - 1);
86}
87
88/**
89 * Copy a libwifi_beacon into a regular unsigned char buffer. This is useful when injecting generated
90 * libwifi frames.
91 */
92size_t libwifi_dump_beacon(struct libwifi_beacon *beacon, unsigned char *buf, size_t buf_len) {
93 size_t beacon_len = libwifi_get_beacon_length(beacon);
94 if (beacon_len > buf_len) {
95 return -EINVAL;
96 }
97
98 size_t offset = 0;
99 memcpy(buf + offset, &beacon->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header));
100 offset += sizeof(struct libwifi_mgmt_unordered_frame_header);
101
102 memcpy(buf + offset, &beacon->fixed_parameters, sizeof(struct libwifi_beacon_fixed_parameters));
103 offset += sizeof(struct libwifi_beacon_fixed_parameters);
104
105 memcpy(buf + offset, beacon->tags.parameters, beacon->tags.length);
106 offset += beacon->tags.length;
107
108 return beacon_len;
109}
110
111/**
112 * Because the tagged parameters memory is managed inside of the library, the library must
113 * be the one to free it, too.
114 */
115void libwifi_free_beacon(struct libwifi_beacon *beacon) {
116 free(beacon->tags.parameters);
117}
diff --git a/src/libwifi/gen/management/beacon.h b/src/libwifi/gen/management/beacon.h new file mode 100644 index 0000000..3da342b --- /dev/null +++ b/src/libwifi/gen/management/beacon.h
@@ -0,0 +1,78 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_GEN_BEACON_H
17#define LIBWIFI_GEN_BEACON_H
18
19#include "../../core/frame/management/beacon.h"
20
21/**
22 * Set the SSID of a struct libwifi_beacon.
23 *
24 * @param beacon A struct libwifi_beacon
25 * @param ssid The new SSID
26 */
27void libwifi_set_beacon_ssid(struct libwifi_beacon *beacon, const char *ssid);
28
29/**
30 * Set the channel of a struct libwifi_beacon.
31 *
32 * @param beacon A struct libwifi_beacon
33 * @param channel The new channel
34 */
35void libwifi_set_beacon_channel(struct libwifi_beacon *beacon, uint8_t channel);
36
37/**
38 * Calculate the length of a given struct libwifi_beacon
39 *
40 * @param beacon A struct libwifi_beacon
41 * @return The length of the given beacon
42 */
43size_t libwifi_get_beacon_length(struct libwifi_beacon *beacon);
44
45/**
46 * Generate a populated libwifi beacon.
47 *
48 * A generated libwifi beacon can be "dumped" into a buffer for packet injection
49 * via the libwifi_dump_beacon.
50 *
51 * @param beacon A struct libwifi_beacon
52 * @param receiver The receiver MAC address, aka address 1
53 * @param transmitter The source MAC address, aka address 2
54 * @param ssid The SSID of the beacon. Maximum length is 32 characters
55 * @param channel The desired channel of the beacon
56 *
57 */
58void libwifi_create_beacon(struct libwifi_beacon *beacon, const unsigned char receiver[6],
59 const unsigned char transmitter[6], const char *ssid, uint8_t channel);
60
61/**
62 * Dump a struct libwifi_beacon into a raw format for packet injection.
63 *
64 * @param beacon A struct libwifi_beacon
65 * @param buf The output buffer for the frame data
66 * @param buf_len The length of the output buffer
67 * @return The length of the dumped beacon
68 */
69size_t libwifi_dump_beacon(struct libwifi_beacon *beacon, unsigned char *buf, size_t buf_len);
70
71/**
72 * Free any memory claimed by a struct libwifi_beacon back to the system.
73 *
74 * @param beacon A struct libwifi_beacon
75 */
76void libwifi_free_beacon(struct libwifi_beacon *beacon);
77
78#endif /* LIBWIFI_GEN_BEACON_H */
diff --git a/src/libwifi/gen/management/common.h b/src/libwifi/gen/management/common.h new file mode 100644 index 0000000..ec3b744 --- /dev/null +++ b/src/libwifi/gen/management/common.h
@@ -0,0 +1,54 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_GEN_COMMON_H
17#define LIBWIFI_GEN_COMMON_H
18
19/**
20 * A sane default for an AP-side capabilities information field.
21 *
22 * 0x0001 = Transmitter is an AP
23 */
24#define LIBWIFI_DEFAULT_AP_CAPABS 0x0001
25
26/**
27 * A sane default for an STA-side capabilities information field.
28 *
29 * 0x0000 = None
30 */
31#define LIBWIFI_DEFAULT_STA_CAPABS 0x0000
32
33/**
34 * A sane default for the listen_interval field.
35 *
36 * 0x0001 = 1 Beacon Interval
37 */
38#define LIBWIFI_DEFAULT_LISTEN_INTERVAL 0x0001
39
40/**
41 * A sane default for a beacon_interval field.
42 *
43 * 0x0064 = 0.1024 Seconds
44 */
45#define LIBWIFI_DEFAULT_BEACON_INTERVAL 0x0064
46
47/**
48 * A sane default for the supported rates frame field.
49 *
50 * 1, 2, 5.5, 11, 18, 24, 36, 54 Mbit/s
51 */
52#define LIBWIFI_DEFAULT_SUPP_RATES "\x82\x84\x8b\x96\x24\x30\x48\x6c"
53
54#endif /* LIBWIFI_GEN_COMMON_H */
diff --git a/src/libwifi/gen/management/deauthentication.c b/src/libwifi/gen/management/deauthentication.c new file mode 100644 index 0000000..14f2c26 --- /dev/null +++ b/src/libwifi/gen/management/deauthentication.c
@@ -0,0 +1,82 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "deauthentication.h"
17#include "../../core/misc/byteswap.h"
18
19#include <errno.h>
20#include <stdlib.h>
21#include <string.h>
22
23/**
24 * The length of a deauth frame is the sum of the header length, the fixed parameters length, and the tagged
25 * parameters length.
26 */
27size_t libwifi_get_deauth_length(struct libwifi_deauth *deauth) {
28 return sizeof(struct libwifi_mgmt_unordered_frame_header) +
29 sizeof(struct libwifi_deauth_fixed_parameters) + deauth->tags.length;
30}
31
32/**
33 * The generated deauthentication frame contains only the supplied receiver, transmitter and reason_code by
34 * default.
35 */
36int libwifi_create_deauth(struct libwifi_deauth *deauth, const unsigned char receiver[6],
37 const unsigned char transmitter[6], uint16_t reason_code) {
38 memset(deauth, 0, sizeof(struct libwifi_deauth));
39
40 deauth->frame_header.frame_control.type = TYPE_MANAGEMENT;
41 deauth->frame_header.frame_control.subtype = SUBTYPE_DEAUTH;
42 memcpy(&deauth->frame_header.addr1, receiver, 6);
43 memcpy(&deauth->frame_header.addr2, transmitter, 6);
44 memcpy(&deauth->frame_header.addr3, transmitter, 6);
45
46 deauth->frame_header.seq_control.sequence_number = (rand() % 4096);
47
48 memcpy(&deauth->fixed_parameters.reason_code, &reason_code, sizeof(reason_code));
49
50 return 0;
51}
52
53/**
54 * Copy a libwifi_deauth into a regular unsigned char buffer. This is useful when injecting generated
55 * libwifi frames.
56 */
57size_t libwifi_dump_deauth(struct libwifi_deauth *deauth, unsigned char *buf, size_t buf_len) {
58 size_t deauth_len = libwifi_get_deauth_length(deauth);
59 if (deauth_len > buf_len) {
60 return -EINVAL;
61 }
62
63 size_t offset = 0;
64 memcpy(buf + offset, &deauth->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header));
65 offset += sizeof(struct libwifi_mgmt_unordered_frame_header);
66
67 memcpy(buf + offset, &deauth->fixed_parameters, sizeof(struct libwifi_deauth_fixed_parameters));
68 offset += sizeof(struct libwifi_deauth_fixed_parameters);
69
70 memcpy(buf + offset, deauth->tags.parameters, deauth->tags.length);
71 offset += deauth->tags.length;
72
73 return deauth_len;
74}
75
76/**
77 * Because the tagged parameters memory is managed inside of the library, the library must
78 * be the one to free it, too.
79 */
80void libwifi_free_deauth(struct libwifi_deauth *deauth) {
81 free(deauth->tags.parameters);
82}
diff --git a/src/libwifi/gen/management/deauthentication.h b/src/libwifi/gen/management/deauthentication.h new file mode 100644 index 0000000..902241d --- /dev/null +++ b/src/libwifi/gen/management/deauthentication.h
@@ -0,0 +1,63 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_GEN_DEAUTH_H
17#define LIBWIFI_GEN_DEAUTH_H
18
19#include <stdint.h>
20
21#include "../../core/frame/management/deauthentication.h"
22
23/**
24 * Calculate the length of a given libwifi_deauth
25 *
26 * @param deauth A libwifi_deauth
27 * @return The length of the given deauth
28 */
29size_t libwifi_get_deauth_length(struct libwifi_deauth *deauth);
30
31/**
32 * Generate a populated libwifi deauth.
33 *
34 * A generated libwifi deauth can be "dumped" into a buffer for packet injection
35 * via the libwifi_dump_deauth.
36 *
37 * @param deauth A libwifi_deauth
38 * @param receiver The receiver MAC address, aka address 1
39 * @param transmitter The source MAC address, aka address 2
40 * @param reason_code The deauth reason code
41 *
42 */
43int libwifi_create_deauth(struct libwifi_deauth *deauth, const unsigned char receiver[6],
44 const unsigned char transmitter[6], uint16_t reason_code);
45
46/**
47 * Dump a libwifi_deauth into a raw format for packet injection.
48 *
49 * @param deauth A libwifi_deauth
50 * @param buf The output buffer for the frame data
51 * @param buf_len The length of the output buffer
52 * @return The length of the dumped deauth
53 */
54size_t libwifi_dump_deauth(struct libwifi_deauth *deauth, unsigned char *buf, size_t buf_len);
55
56/**
57 * Free any memory claimed by a libwifi_deauth back to the system.
58 *
59 * @param deauth A libwifi_deauth
60 */
61void libwifi_free_deauth(struct libwifi_deauth *deauth);
62
63#endif /* LIBWIFI_GEN_DEAUTH_H */
diff --git a/src/libwifi/gen/management/disassociation.c b/src/libwifi/gen/management/disassociation.c new file mode 100644 index 0000000..a885efd --- /dev/null +++ b/src/libwifi/gen/management/disassociation.c
@@ -0,0 +1,80 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "disassociation.h"
17#include "../../core/misc/byteswap.h"
18
19#include <errno.h>
20#include <stdlib.h>
21#include <string.h>
22
23/**
24 * The length of a disassoc frame is the sum of the header length, the fixed parameters length, and the tagged
25 * parameters length.
26 */
27size_t libwifi_get_disassoc_length(struct libwifi_disassoc *disassoc) {
28 return sizeof(struct libwifi_mgmt_unordered_frame_header) +
29 sizeof(struct libwifi_disassoc_fixed_parameters) + disassoc->tags.length;
30}
31
32/**
33 * The generated disassociation frame contains only the supplied receiver, transmitter and reason_code by
34 * default.
35 */
36void libwifi_create_disassoc(struct libwifi_disassoc *disassoc, const unsigned char receiver[6],
37 const unsigned char transmitter[6], uint16_t reason_code) {
38 memset(disassoc, 0, sizeof(struct libwifi_disassoc));
39
40 disassoc->frame_header.frame_control.type = TYPE_MANAGEMENT;
41 disassoc->frame_header.frame_control.subtype = SUBTYPE_DISASSOC;
42 memcpy(&disassoc->frame_header.addr1, receiver, 6);
43 memcpy(&disassoc->frame_header.addr2, transmitter, 6);
44 memcpy(&disassoc->frame_header.addr3, transmitter, 6);
45
46 disassoc->frame_header.seq_control.sequence_number = (rand() % 4096);
47
48 memcpy(&disassoc->fixed_parameters.reason_code, &reason_code, sizeof(reason_code));
49}
50
51/**
52 * Copy a libwifi_disassoc into a regular unsigned char buffer. This is useful when injecting generated
53 * libwifi frames.
54 */
55size_t libwifi_dump_disassoc(struct libwifi_disassoc *disassoc, unsigned char *buf, size_t buf_len) {
56 size_t disassoc_len = libwifi_get_disassoc_length(disassoc);
57 if (disassoc_len > buf_len) {
58 return -EINVAL;
59 }
60
61 size_t offset = 0;
62 memcpy(buf + offset, &disassoc->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header));
63 offset += sizeof(struct libwifi_mgmt_unordered_frame_header);
64
65 memcpy(buf + offset, &disassoc->fixed_parameters, sizeof(struct libwifi_disassoc_fixed_parameters));
66 offset += sizeof(struct libwifi_disassoc_fixed_parameters);
67
68 memcpy(buf + offset, disassoc->tags.parameters, disassoc->tags.length);
69 offset += disassoc->tags.length;
70
71 return disassoc_len;
72}
73
74/**
75 * Because the tagged parameters memory is managed inside of the library, the library must
76 * be the one to free it, too.
77 */
78void libwifi_free_disassoc(struct libwifi_disassoc *disassoc) {
79 free(disassoc->tags.parameters);
80}
diff --git a/src/libwifi/gen/management/disassociation.h b/src/libwifi/gen/management/disassociation.h new file mode 100644 index 0000000..fada9f0 --- /dev/null +++ b/src/libwifi/gen/management/disassociation.h
@@ -0,0 +1,63 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_GEN_DISASSOC_H
17#define LIBWIFI_GEN_DISASSOC_H
18
19#include <stdint.h>
20
21#include "../../core/frame/management/disassociation.h"
22
23/**
24 * Calculate the length of a given libwifi_disassoc
25 *
26 * @param disassoc A libwifi_disassoc
27 * @return The length of the given disassoc
28 */
29size_t libwifi_get_disassoc_length(struct libwifi_disassoc *disassoc);
30
31/**
32 * Generate a populated libwifi disassoc.
33 *
34 * A generated libwifi disassoc can be "dumped" into a buffer for packet injection
35 * via the libwifi_dump_disassoc.
36 *
37 * @param disassoc A libwifi_disassoc
38 * @param receiver The receiver MAC address, aka address 1
39 * @param transmitter The source MAC address, aka address 2
40 * @param reason_code The disassoc reason code
41 *
42 */
43void libwifi_create_disassoc(struct libwifi_disassoc *disassoc, const unsigned char receiver[6],
44 const unsigned char transmitter[6], uint16_t reason_code);
45
46/**
47 * Dump a libwifi_disassoc into a raw format for packet injection.
48 *
49 * @param disassoc A libwifi_disassoc
50 * @param buf The output buffer for the frame data
51 * @param buf_len The length of the output buffer
52 * @return The length of the dumped disassoc
53 */
54size_t libwifi_dump_disassoc(struct libwifi_disassoc *disassoc, unsigned char *buf, size_t buf_len);
55
56/**
57 * Free any memory claimed by a libwifi_disassoc back to the system.
58 *
59 * @param disassoc A libwifi_disassoc
60 */
61void libwifi_free_disassoc(struct libwifi_disassoc *disassoc);
62
63#endif /* LIBWIFI_GEN_DISASSOC_H */
diff --git a/src/libwifi/gen/management/probe_request.c b/src/libwifi/gen/management/probe_request.c new file mode 100644 index 0000000..7c5b99e --- /dev/null +++ b/src/libwifi/gen/management/probe_request.c
@@ -0,0 +1,76 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "probe_request.h"
17#include "../../core/misc/byteswap.h"
18
19#include <errno.h>
20#include <stdlib.h>
21#include <string.h>
22
23/**
24 * The length of a probe request frame is the sum of the header length plus the tagged parameters length.
25 */
26size_t libwifi_get_probe_req_length(struct libwifi_probe_req *probe_req) {
27 return sizeof(struct libwifi_mgmt_unordered_frame_header) + probe_req->tags.length;
28}
29
30/**
31 * The generated probe request frame is made with sane defaults defined in common.h.
32 * Two tagged parameters are also added to the beacon: SSID and Channel.
33 */
34void libwifi_create_probe_req(struct libwifi_probe_req *probe_req, const unsigned char receiver[6],
35 const unsigned char transmitter[6], const unsigned char bssid[6],
36 const char *ssid, uint8_t channel) {
37 memset(probe_req, 0, sizeof(struct libwifi_probe_req));
38
39 probe_req->frame_header.frame_control.type = TYPE_MANAGEMENT;
40 probe_req->frame_header.frame_control.subtype = SUBTYPE_PROBE_REQ;
41 memcpy(&probe_req->frame_header.addr1, receiver, 6);
42 memcpy(&probe_req->frame_header.addr2, transmitter, 6);
43 memcpy(&probe_req->frame_header.addr3, bssid, 6);
44 probe_req->frame_header.seq_control.sequence_number = (rand() % 4096);
45
46 libwifi_quick_add_tag(&probe_req->tags, TAG_SSID, (const unsigned char *) ssid, strlen(ssid));
47 libwifi_quick_add_tag(&probe_req->tags, TAG_DS_PARAMETER, (const unsigned char *) &channel, 1);
48}
49
50/**
51 * Copy a libwifi_probe_req into a regular unsigned char buffer. This is useful when injecting generated
52 * libwifi frames.
53 */
54size_t libwifi_dump_probe_req(struct libwifi_probe_req *probe_req, unsigned char *buf, size_t buf_len) {
55 size_t probe_req_len = libwifi_get_probe_req_length(probe_req);
56 if (probe_req_len > buf_len) {
57 return -EINVAL;
58 }
59
60 size_t offset = 0;
61 memcpy(buf + offset, &probe_req->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header));
62 offset += sizeof(struct libwifi_mgmt_unordered_frame_header);
63
64 memcpy(buf + offset, probe_req->tags.parameters, probe_req->tags.length);
65 offset += probe_req->tags.length;
66
67 return probe_req_len;
68}
69
70/**
71 * Because the tagged parameters memory is managed inside of the library, the library must
72 * be the one to free it, too.
73 */
74void libwifi_free_probe_req(struct libwifi_probe_req *probe_req) {
75 free(probe_req->tags.parameters);
76}
diff --git a/src/libwifi/gen/management/probe_request.h b/src/libwifi/gen/management/probe_request.h new file mode 100644 index 0000000..f98b70a --- /dev/null +++ b/src/libwifi/gen/management/probe_request.h
@@ -0,0 +1,64 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_GEN_PROBEREQ_H
17#define LIBWIFI_GEN_PROBEREQ_H
18
19#include <stdint.h>
20
21#include "../../core/frame/management/probe_request.h"
22
23/**
24 * Calculate the length of a given libwifi_probe_req
25 *
26 * @param probe_req A libwifi_probe_req
27 * @return The length of the given probe_req
28 */
29size_t libwifi_get_probe_req_length(struct libwifi_probe_req *probe_req);
30
31/**
32 * Generate a populated libwifi probe_req.
33 *
34 * A generated libwifi probe_req can be "dumped" into a buffer for packet injection
35 * via the libwifi_dump_probe_req.
36 *
37 * @param probe_req A libwifi_probe_req
38 * @param receiver The receiver MAC address, aka address 1
39 * @param transmitter The source MAC address, aka address 2
40 * @param reason_code The probe_req reason code
41 *
42 */
43void libwifi_create_probe_req(struct libwifi_probe_req *probe_req, const unsigned char receiver[6],
44 const unsigned char transmitter[6], const unsigned char bssid[6],
45 const char *ssid, uint8_t channel);
46
47/**
48 * Dump a libwifi_probe_req into a raw format for packet injection.
49 *
50 * @param probe_req A libwifi_probe_req
51 * @param buf The output buffer for the frame data
52 * @param buf_len The length of the output buffer
53 * @return The length of the dumped probe_req
54 */
55size_t libwifi_dump_probe_req(struct libwifi_probe_req *probe_req, unsigned char *buf, size_t buf_len);
56
57/**
58 * Free any memory claimed by a libwifi_probe_req back to the system.
59 *
60 * @param probe_req A libwifi_probe_req
61 */
62void libwifi_free_probe_req(struct libwifi_probe_req *probe_req);
63
64#endif /* LIBWIFI_GEN_PROBEREQ_H */
diff --git a/src/libwifi/gen/management/probe_response.c b/src/libwifi/gen/management/probe_response.c new file mode 100644 index 0000000..403a8bc --- /dev/null +++ b/src/libwifi/gen/management/probe_response.c
@@ -0,0 +1,118 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "probe_response.h"
17#include "../../core/frame/tag.h"
18#include "../../core/frame/tag_iterator.h"
19#include "../../core/misc/byteswap.h"
20#include "../../core/misc/epoch.h"
21#include "common.h"
22
23#include <errno.h>
24#include <stdint.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <sys/types.h>
29
30/**
31 * The length of a probe response frame is the sum of the header length, the fixed parameters length, and the
32 * tagged parameters length.
33 */
34size_t libwifi_get_probe_resp_length(struct libwifi_probe_resp *probe_resp) {
35 return sizeof(struct libwifi_mgmt_unordered_frame_header) +
36 sizeof(struct libwifi_probe_resp_fixed_parameters) + probe_resp->tags.length;
37}
38
39/**
40 * Simple helper to set the probe response SSID tag by removing it and then adding it back with the new value.
41 */
42void libwifi_set_probe_resp_ssid(struct libwifi_probe_resp *probe_resp, const char *ssid) {
43 if (probe_resp->tags.length != 0) {
44 libwifi_remove_tag(&probe_resp->tags, TAG_SSID);
45 }
46
47 libwifi_quick_add_tag(&probe_resp->tags, TAG_SSID, (void *) ssid, strlen(ssid));
48}
49
50/**
51 * Simple helper to set the probe response DS tag by removing it and then adding it back with the new value.
52 */
53void libwifi_set_probe_resp_channel(struct libwifi_probe_resp *probe_resp, uint8_t channel) {
54 if (probe_resp->tags.length != 0) {
55 libwifi_remove_tag(&probe_resp->tags, TAG_DS_PARAMETER);
56 }
57
58 const unsigned char *chan = (const unsigned char *) &channel;
59
60 libwifi_quick_add_tag(&probe_resp->tags, TAG_DS_PARAMETER, chan, 1);
61}
62
63/**
64 * The generated probe response frame is made with sane defaults defined in common.h.
65 * Three tagged parameters are also added to the probe response: SSID, Channel and Supported Rates.
66 */
67void libwifi_create_probe_resp(struct libwifi_probe_resp *probe_resp, const unsigned char receiver[6],
68 const unsigned char transmitter[6], const char *ssid, uint8_t channel) {
69 memset(probe_resp, 0, sizeof(struct libwifi_probe_resp));
70
71 probe_resp->frame_header.frame_control.type = TYPE_MANAGEMENT;
72 probe_resp->frame_header.frame_control.subtype = SUBTYPE_PROBE_RESP;
73 memcpy(&probe_resp->frame_header.addr1, receiver, 6);
74 memcpy(&probe_resp->frame_header.addr2, transmitter, 6);
75
76 probe_resp->frame_header.seq_control.sequence_number = (rand() % 4096);
77 probe_resp->fixed_parameters.timestamp = BYTESWAP64(libwifi_get_epoch());
78 uint16_t probe_resp_interval = 50 + (rand() % 100);
79 probe_resp->fixed_parameters.probe_resp_interval = BYTESWAP16(probe_resp_interval);
80 probe_resp->fixed_parameters.capabilities_information = BYTESWAP16(LIBWIFI_DEFAULT_AP_CAPABS);
81
82 libwifi_set_probe_resp_ssid(probe_resp, ssid);
83 libwifi_set_probe_resp_channel(probe_resp, channel);
84
85 const unsigned char supported_rates[] = LIBWIFI_DEFAULT_SUPP_RATES;
86 libwifi_quick_add_tag(&probe_resp->tags, TAG_SUPP_RATES, supported_rates, sizeof(supported_rates) - 1);
87}
88
89/**
90 * Copy a libwifi_probe_resp into a regular unsigned char buffer. This is useful when injecting generated
91 * libwifi frames.
92 */
93size_t libwifi_dump_probe_resp(struct libwifi_probe_resp *probe_resp, unsigned char *buf, size_t buf_len) {
94 size_t probe_resp_len = libwifi_get_probe_resp_length(probe_resp);
95 if (probe_resp_len > buf_len) {
96 return -EINVAL;
97 }
98
99 size_t offset = 0;
100 memcpy(buf + offset, &probe_resp->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header));
101 offset += sizeof(struct libwifi_mgmt_unordered_frame_header);
102
103 memcpy(buf + offset, &probe_resp->fixed_parameters, sizeof(struct libwifi_probe_resp_fixed_parameters));
104 offset += sizeof(struct libwifi_probe_resp_fixed_parameters);
105
106 memcpy(buf + offset, probe_resp->tags.parameters, probe_resp->tags.length);
107 offset += probe_resp->tags.length;
108
109 return probe_resp_len;
110}
111
112/**
113 * Because the tagged parameters memory is managed inside of the library, the library must
114 * be the one to free it, too.
115 */
116void libwifi_free_probe_resp(struct libwifi_probe_resp *probe_resp) {
117 free(probe_resp->tags.parameters);
118}
diff --git a/src/libwifi/gen/management/probe_response.h b/src/libwifi/gen/management/probe_response.h new file mode 100644 index 0000000..56243ee --- /dev/null +++ b/src/libwifi/gen/management/probe_response.h
@@ -0,0 +1,78 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_GEN_PROBERESP_H
17#define LIBWIFI_GEN_PROBERESP_H
18
19#include "../../core/frame/management/probe_response.h"
20
21/**
22 * Set the SSID of a libwifi_probe_resp.
23 *
24 * @param probe_resp A libwifi_probe_resp
25 * @param ssid The new SSID
26 */
27void libwifi_set_probe_resp_ssid(struct libwifi_probe_resp *probe_resp, const char *ssid);
28
29/**
30 * Set the channel of a libwifi_probe_resp.
31 *
32 * @param probe_resp A libwifi_probe_resp
33 * @param channel The new channel
34 */
35void libwifi_set_probe_resp_channel(struct libwifi_probe_resp *probe_resp, uint8_t channel);
36
37/**
38 * Calculate the length of a given libwifi_probe_resp
39 *
40 * @param probe_resp A libwifi_probe_resp
41 * @return The length of the given probe_resp
42 */
43size_t libwifi_get_probe_resp_length(struct libwifi_probe_resp *probe_resp);
44
45/**
46 * Generate a populated libwifi probe_resp.
47 *
48 * A generated libwifi probe_resp can be "dumped" into a buffer for packet injection
49 * via the libwifi_dump_probe_resp.
50 *
51 * @param probe_resp A libwifi_probe_resp
52 * @param receiver The receiver MAC address, aka address 1
53 * @param transmitter The source MAC address, aka address 2
54 * @param ssid The SSID of the probe_resp. Maximum length is 32 characters
55 * @param channel The desired channel of the probe_resp
56 *
57 */
58void libwifi_create_probe_resp(struct libwifi_probe_resp *probe_resp, const unsigned char receiver[6],
59 const unsigned char transmitter[6], const char *ssid, uint8_t channel);
60
61/**
62 * Dump a libwifi_probe_resp into a raw format for packet injection.
63 *
64 * @param probe_resp A libwifi_probe_resp
65 * @param buf The output buffer for the frame data
66 * @param buf_len The length of the output buffer
67 * @return The length of the dumped probe_resp
68 */
69size_t libwifi_dump_probe_resp(struct libwifi_probe_resp *probe_resp, unsigned char *buf, size_t buf_len);
70
71/**
72 * Free any memory claimed by a libwifi_probe_resp back to the system.
73 *
74 * @param probe_resp A libwifi_probe_resp
75 */
76void libwifi_free_probe_resp(struct libwifi_probe_resp *probe_resp);
77
78#endif /* LIBWIFI_GEN_PROBERESP_H */
diff --git a/src/libwifi/gen/management/reassoc_request.c b/src/libwifi/gen/management/reassoc_request.c new file mode 100644 index 0000000..f678caf --- /dev/null +++ b/src/libwifi/gen/management/reassoc_request.c
@@ -0,0 +1,87 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "reassoc_request.h"
17#include "common.h"
18
19#include <errno.h>
20#include <stdlib.h>
21#include <string.h>
22
23/**
24 * The length of a reassociation request frame is the sum of the header length, the fixed parameters length,
25 * and the tagged parameters length.
26 */
27size_t libwifi_get_reassoc_req_length(struct libwifi_reassoc_req *reassoc_req) {
28 return sizeof(struct libwifi_mgmt_unordered_frame_header) +
29 sizeof(struct libwifi_reassoc_req_fixed_parameters) + reassoc_req->tags.length;
30}
31
32/**
33 * The generated reassociation request frame is made with sane defaults defined in common.h.
34 * Two tagged parameters are also added to the reassociation frame: SSID and Channel
35 */
36int libwifi_create_reassoc_req(struct libwifi_reassoc_req *reassoc_req, const unsigned char receiver[6],
37 const unsigned char transmitter[6], const unsigned char current_ap[6],
38 const char *ssid, uint8_t channel) {
39 memset(reassoc_req, 0, sizeof(struct libwifi_reassoc_req));
40
41 reassoc_req->frame_header.frame_control.type = TYPE_MANAGEMENT;
42 reassoc_req->frame_header.frame_control.subtype = SUBTYPE_REASSOC_REQ;
43 memcpy(&reassoc_req->frame_header.addr1, receiver, 6);
44 memcpy(&reassoc_req->frame_header.addr2, transmitter, 6);
45 memcpy(&reassoc_req->frame_header.addr3, receiver, 6);
46 reassoc_req->frame_header.seq_control.sequence_number = (rand() % 4096);
47
48 reassoc_req->fixed_parameters.capabilities_information = BYTESWAP16(LIBWIFI_DEFAULT_AP_CAPABS);
49 reassoc_req->fixed_parameters.listen_interval = BYTESWAP16(LIBWIFI_DEFAULT_LISTEN_INTERVAL);
50 memcpy(&reassoc_req->fixed_parameters.current_ap_address, current_ap, 6);
51
52 libwifi_quick_add_tag(&reassoc_req->tags, TAG_SSID, (const unsigned char *) ssid, strlen(ssid));
53 libwifi_quick_add_tag(&reassoc_req->tags, TAG_DS_PARAMETER, (const unsigned char *) &channel, 1);
54
55 return 0;
56}
57
58/**
59 * Copy a libwifi_reassoc_req into a regular unsigned char buffer. This is useful when injecting generated
60 * libwifi frames.
61 */
62size_t libwifi_dump_reassoc_req(struct libwifi_reassoc_req *reassoc_req, unsigned char *buf, size_t buf_len) {
63 size_t reassoc_req_len = libwifi_get_reassoc_req_length(reassoc_req);
64 if (reassoc_req_len > buf_len) {
65 return -EINVAL;
66 }
67
68 size_t offset = 0;
69 memcpy(buf + offset, &reassoc_req->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header));
70 offset += sizeof(struct libwifi_mgmt_unordered_frame_header);
71
72 memcpy(buf + offset, &reassoc_req->fixed_parameters, sizeof(struct libwifi_reassoc_req_fixed_parameters));
73 offset += sizeof(struct libwifi_reassoc_req_fixed_parameters);
74
75 memcpy(buf + offset, reassoc_req->tags.parameters, reassoc_req->tags.length);
76 offset += reassoc_req->tags.length;
77
78 return reassoc_req_len;
79}
80
81/**
82 * Because the tagged parameters memory is managed inside of the library, the library must
83 * be the one to free it, too.
84 */
85void libwifi_free_reassoc_req(struct libwifi_reassoc_req *reassoc_req) {
86 free(reassoc_req->tags.parameters);
87}
diff --git a/src/libwifi/gen/management/reassoc_request.h b/src/libwifi/gen/management/reassoc_request.h new file mode 100644 index 0000000..3db971f --- /dev/null +++ b/src/libwifi/gen/management/reassoc_request.h
@@ -0,0 +1,30 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_GEN_REASSOCREQUEST_H
17#define LIBWIFI_GEN_REASSOCREQUEST_H
18
19#include "../../core/frame/frame.h"
20#include "../../core/frame/management/common.h"
21#include "../../core/frame/management/reassoc_request.h"
22
23int libwifi_create_reassoc_req(struct libwifi_reassoc_req *reassoc_req, const unsigned char receiver[6],
24 const unsigned char transmitter[6], const unsigned char current_ap[6],
25 const char *ssid, uint8_t channel);
26size_t libwifi_get_reassoc_req_length(struct libwifi_reassoc_req *reassoc_req);
27size_t libwifi_dump_reassoc_req(struct libwifi_reassoc_req *reassoc_req, unsigned char *buf, size_t buf_len);
28void libwifi_free_reassoc_req(struct libwifi_reassoc_req *reassoc_req);
29
30#endif /* LIBWIFI_GEN_REASSOCREQUEST_H */
diff --git a/src/libwifi/gen/management/reassoc_response.c b/src/libwifi/gen/management/reassoc_response.c new file mode 100644 index 0000000..b9acbb6 --- /dev/null +++ b/src/libwifi/gen/management/reassoc_response.c
@@ -0,0 +1,108 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "reassoc_response.h"
17#include "../../core/frame/tag.h"
18#include "../../core/frame/tag_iterator.h"
19#include "../../core/misc/byteswap.h"
20#include "../../core/misc/epoch.h"
21#include "../../core/misc/types.h"
22#include "common.h"
23
24#include <errno.h>
25#include <stdint.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <sys/types.h>
30
31/**
32 * The length of a reassociation response frame is the sum of the header length, the fixed parameters length,
33 * and the tagged parameters length.
34 */
35size_t libwifi_get_reassoc_resp_length(struct libwifi_reassoc_resp *reassoc_resp) {
36 return sizeof(struct libwifi_mgmt_unordered_frame_header) +
37 sizeof(struct libwifi_reassoc_resp_fixed_parameters) + reassoc_resp->tags.length;
38}
39
40/**
41 * Simple helper to set the reassociation response DS tag by removing it and then adding it back with the new
42 * value.
43 */
44void libwifi_set_reassoc_resp_channel(struct libwifi_reassoc_resp *reassoc_resp, uint8_t channel) {
45 if (reassoc_resp->tags.length != 0) {
46 libwifi_remove_tag(&reassoc_resp->tags, TAG_DS_PARAMETER);
47 }
48
49 const unsigned char *chan = (const unsigned char *) &channel;
50
51 libwifi_quick_add_tag(&reassoc_resp->tags, TAG_DS_PARAMETER, chan, 1);
52}
53
54/**
55 * The generated reassoc_resp frame is made with sane defaults defined in common.h.
56 * Three tagged parameters are also added to the reassoc_resp: SSID, Channel and Supported Rates.
57 */
58void libwifi_create_reassoc_resp(struct libwifi_reassoc_resp *reassoc_resp, const unsigned char receiver[6],
59 const unsigned char transmitter[6], uint8_t channel) {
60 memset(reassoc_resp, 0, sizeof(struct libwifi_reassoc_resp));
61
62 reassoc_resp->frame_header.frame_control.type = TYPE_MANAGEMENT;
63 reassoc_resp->frame_header.frame_control.subtype = SUBTYPE_REASSOC_RESP;
64 memcpy(&reassoc_resp->frame_header.addr1, receiver, 6);
65 memcpy(&reassoc_resp->frame_header.addr2, transmitter, 6);
66
67 reassoc_resp->fixed_parameters.capabilities_information = BYTESWAP16(LIBWIFI_DEFAULT_AP_CAPABS);
68 reassoc_resp->fixed_parameters.status_code = STATUS_SUCCESS;
69 reassoc_resp->fixed_parameters.association_id = rand() % 4096;
70
71 libwifi_set_reassoc_resp_channel(reassoc_resp, channel);
72
73 const unsigned char supported_rates[] = LIBWIFI_DEFAULT_SUPP_RATES;
74 libwifi_quick_add_tag(&reassoc_resp->tags, TAG_SUPP_RATES, supported_rates, sizeof(supported_rates) - 1);
75}
76
77/**
78 * Copy a libwifi_reassoc_resp into a regular unsigned char buffer. This is useful when injecting generated
79 * libwifi frames.
80 */
81size_t libwifi_dump_reassoc_resp(struct libwifi_reassoc_resp *reassoc_resp, unsigned char *buf,
82 size_t buf_len) {
83 size_t reassoc_resp_len = libwifi_get_reassoc_resp_length(reassoc_resp);
84 if (reassoc_resp_len > buf_len) {
85 return -EINVAL;
86 }
87
88 size_t offset = 0;
89 memcpy(buf + offset, &reassoc_resp->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header));
90 offset += sizeof(struct libwifi_mgmt_unordered_frame_header);
91
92 memcpy(buf + offset, &reassoc_resp->fixed_parameters,
93 sizeof(struct libwifi_reassoc_resp_fixed_parameters));
94 offset += sizeof(struct libwifi_reassoc_resp_fixed_parameters);
95
96 memcpy(buf + offset, reassoc_resp->tags.parameters, reassoc_resp->tags.length);
97 offset += reassoc_resp->tags.length;
98
99 return reassoc_resp_len;
100}
101
102/**
103 * Because the tagged parameters memory is managed inside of the library, the library must
104 * be the one to free it, too.
105 */
106void libwifi_free_reassoc_resp(struct libwifi_reassoc_resp *reassoc_resp) {
107 free(reassoc_resp->tags.parameters);
108}
diff --git a/src/libwifi/gen/management/reassoc_response.h b/src/libwifi/gen/management/reassoc_response.h new file mode 100644 index 0000000..f0a2da2 --- /dev/null +++ b/src/libwifi/gen/management/reassoc_response.h
@@ -0,0 +1,70 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_GEN_REASSOCRESP_H
17#define LIBWIFI_GEN_REASSOCRESP_H
18
19#include "../../core/frame/management/reassoc_response.h"
20
21/**
22 * Set the channel of a libwifi_reassoc_resp.
23 *
24 * @param reassoc_resp A libwifi_reassoc_resp
25 * @param channel The new channel
26 */
27void libwifi_set_reassoc_resp_channel(struct libwifi_reassoc_resp *reassoc_resp, uint8_t channel);
28
29/**
30 * Calculate the length of a given libwifi_reassoc_resp
31 *
32 * @param reassoc_resp A libwifi_reassoc_resp
33 * @return The length of the given reassoc_resp
34 */
35size_t libwifi_get_reassoc_resp_length(struct libwifi_reassoc_resp *reassoc_resp);
36
37/**
38 * Generate a populated libwifi reassoc_resp.
39 *
40 * A generated libwifi reassoc_resp can be "dumped" into a buffer for packet injection
41 * via the libwifi_dump_reassoc_resp.
42 *
43 * @param reassoc_resp A libwifi_reassoc_resp
44 * @param receiver The receiver MAC address, aka address 1
45 * @param transmitter The source MAC address, aka address 2
46 * @param channel The desired channel of the reassoc_resp
47 *
48 */
49void libwifi_create_reassoc_resp(struct libwifi_reassoc_resp *reassoc_resp, const unsigned char receiver[6],
50 const unsigned char transmitter[6], uint8_t channel);
51
52/**
53 * Dump a libwifi_reassoc_resp into a raw format for packet injection.
54 *
55 * @param reassoc_resp A libwifi_reassoc_resp
56 * @param buf The output buffer for the frame data
57 * @param buf_len The length of the output buffer
58 * @return The length of the dumped reassoc_resp
59 */
60size_t libwifi_dump_reassoc_resp(struct libwifi_reassoc_resp *reassoc_resp, unsigned char *buf,
61 size_t buf_len);
62
63/**
64 * Free any memory claimed by a libwifi_reassoc_resp back to the system.
65 *
66 * @param reassoc_resp A libwifi_reassoc_resp
67 */
68void libwifi_free_reassoc_resp(struct libwifi_reassoc_resp *reassoc_resp);
69
70#endif /* LIBWIFI_GEN_REASSOCRESP_H */
diff --git a/src/libwifi/gen/management/timing_ad.c b/src/libwifi/gen/management/timing_ad.c new file mode 100644 index 0000000..6e67a6b --- /dev/null +++ b/src/libwifi/gen/management/timing_ad.c
@@ -0,0 +1,111 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "common.h"
17#include "timing_ad.h"
18#include "../../core/frame/management/timing_ad.h"
19#include "../../core/misc/epoch.h"
20#include "../../core/frame/tag.h"
21
22#include <stdlib.h>
23#include <string.h>
24
25void libwifi_create_timing_advert(struct libwifi_timing_advert *adv, const unsigned char destination[6],
26 const unsigned char transmitter[6], struct libwifi_timing_advert_fields *adv_fields,
27 const char country[3], uint16_t max_reg_power, uint8_t max_tx_power, uint8_t tx_power_used,
28 uint8_t noise_floor) {
29 memset(adv, 0, sizeof(struct libwifi_timing_advert));
30
31 adv->frame_header.frame_control.type = TYPE_MANAGEMENT;
32 adv->frame_header.frame_control.subtype = SUBTYPE_TIME_ADV;
33 memcpy(&adv->frame_header.addr1, destination, 6);
34 memcpy(&adv->frame_header.addr2, transmitter, 6);
35 adv->frame_header.seq_control.sequence_number = (rand() % 4096);
36
37 adv->fixed_parameters.timestamp = BYTESWAP64(libwifi_get_epoch());
38 adv->fixed_parameters.measurement_pilot_interval = LIBWIFI_DEFAULT_BEACON_INTERVAL;
39 adv->fixed_parameters.beacon_interval = LIBWIFI_DEFAULT_BEACON_INTERVAL;
40 adv->fixed_parameters.capabilities_information = BYTESWAP16(LIBWIFI_DEFAULT_AP_CAPABS);
41 memcpy(adv->fixed_parameters.country, country, sizeof(adv->fixed_parameters.country));
42 adv->fixed_parameters.max_reg_power = BYTESWAP16(max_reg_power);
43 adv->fixed_parameters.max_tx_power = max_tx_power;
44 adv->fixed_parameters.tx_power_used = tx_power_used;
45 adv->fixed_parameters.noise_floor = noise_floor;
46
47 if (adv_fields == NULL) {
48 return;
49 }
50
51 // Maximum element size is 17
52 unsigned char element_data[17] = {0};
53 size_t element_data_len = 0;
54 int offset = 0;
55
56 memcpy(element_data, &adv_fields->timing_capabilities, sizeof(adv_fields->timing_capabilities));
57 offset += sizeof(adv_fields->timing_capabilities);
58
59 switch (adv_fields->timing_capabilities) {
60 case 1: { /* Time Value and Time Error fields present */
61 memcpy(element_data + offset, &adv_fields->time_value, sizeof(adv_fields->time_value));
62 offset += sizeof(adv_fields->time_value);
63 memcpy(element_data + offset, &adv_fields->time_error, sizeof(adv_fields->time_error));
64 offset += sizeof(adv_fields->time_error);
65 break;
66 }
67 case 2: { /* Time Value, Time Error, and Time Update fields present */
68 memcpy(element_data + offset, &adv_fields->time_value, sizeof(adv_fields->time_value));
69 offset += sizeof(adv_fields->time_value);
70 memcpy(element_data + offset, &adv_fields->time_error, sizeof(adv_fields->time_error));
71 offset += sizeof(adv_fields->time_error);
72 memcpy(element_data + offset, &adv_fields->time_update, sizeof(adv_fields->time_update));
73 offset += sizeof(adv_fields->time_update);
74 }
75 default:
76 break;
77 }
78
79 element_data_len = offset;
80
81 libwifi_quick_add_tag(&adv->tags, TAG_TIME_ADVERTISEMENT, element_data, element_data_len);
82}
83
84size_t libwifi_get_timing_advert_length(struct libwifi_timing_advert *adv) {
85 return sizeof(struct libwifi_mgmt_unordered_frame_header) +
86 sizeof(struct libwifi_timing_advert_fixed_params) +
87 adv->tags.length;
88}
89
90size_t libwifi_dump_timing_advert(struct libwifi_timing_advert *adv, unsigned char *buf, size_t buf_len) {
91 size_t adv_len = libwifi_get_timing_advert_length(adv);
92 if (adv_len > buf_len) {
93 return -1;
94 }
95
96 size_t offset = 0;
97 memcpy(buf + offset, &adv->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header));
98 offset += sizeof(struct libwifi_mgmt_unordered_frame_header);
99
100 memcpy(buf + offset, &adv->fixed_parameters, sizeof(struct libwifi_timing_advert_fixed_params));
101 offset += sizeof(struct libwifi_timing_advert_fixed_params);
102
103 memcpy(buf + offset, adv->tags.parameters, adv->tags.length);
104 offset += adv->tags.length;
105
106 return adv_len;
107}
108
109void libwifi_free_timing_advert(struct libwifi_timing_advert *adv) {
110 free(adv->tags.parameters);
111}
diff --git a/src/libwifi/gen/management/timing_ad.h b/src/libwifi/gen/management/timing_ad.h new file mode 100644 index 0000000..cdcb827 --- /dev/null +++ b/src/libwifi/gen/management/timing_ad.h
@@ -0,0 +1,32 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_GEN_TIMINGAD_H
17#define LIBWIFI_GEN_TIMINGAD_H
18
19#include "../../core/frame/management/timing_ad.h"
20
21void libwifi_create_timing_advert(struct libwifi_timing_advert *adv, const unsigned char destination[6],
22 const unsigned char transmitter[6], struct libwifi_timing_advert_fields *adv_fields,
23 const char country[3], uint16_t max_reg_power, uint8_t max_tx_power, uint8_t tx_power_used,
24 uint8_t noise_floor);
25
26size_t libwifi_get_timing_advert_length(struct libwifi_timing_advert *adv);
27
28size_t libwifi_dump_timing_advert(struct libwifi_timing_advert *adv, unsigned char *buf, size_t buf_len);
29
30void libwifi_free_timing_advert(struct libwifi_timing_advert *adv);
31
32#endif /* LIBWIFI_GEN_TIMINGAD_H */
diff --git a/src/libwifi/gen/misc/radiotap.c b/src/libwifi/gen/misc/radiotap.c new file mode 100644 index 0000000..cc02097 --- /dev/null +++ b/src/libwifi/gen/misc/radiotap.c
@@ -0,0 +1,123 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "radiotap.h"
17#include "../../core/radiotap/radiotap.h"
18#include "../../core/radiotap/radiotap_iter.h"
19
20#include <stdint.h>
21#include <stdlib.h>
22#include <string.h>
23
24#define LIBWIFI_RADIOTAP_HEADER_LEN 8
25
26size_t libwifi_create_radiotap(struct libwifi_radiotap_info *info, char *radiotap_header) {
27 struct ieee80211_radiotap_header rtap_hdr = {0};
28 rtap_hdr.it_version = 0;
29 rtap_hdr.it_pad = 0;
30 rtap_hdr.it_present = info->present;
31 rtap_hdr.it_len = sizeof(struct ieee80211_radiotap_header);
32
33 char rtap_data[LIBWIFI_MAX_RADIOTAP_LEN - LIBWIFI_RADIOTAP_HEADER_LEN] = {0};
34 int offset = 0;
35
36 uint32_t presence_bit = rtap_hdr.it_present;
37 for (int field = 0; field < radiotap_ns.n_bits; field++) {
38 if (presence_bit & 1) {
39 switch (field) {
40 case IEEE80211_RADIOTAP_CHANNEL:
41 memcpy(rtap_data + offset, &info->channel.freq, sizeof(info->channel.freq));
42 offset += sizeof(info->channel.freq);
43 memcpy(rtap_data + offset, &info->channel.flags, sizeof(info->channel.flags));
44 offset += sizeof(info->channel.flags);
45 break;
46 case IEEE80211_RADIOTAP_RATE:
47 memcpy(rtap_data + offset, &info->rate_raw, sizeof(info->rate_raw));
48 offset += sizeof(info->rate_raw);
49 break;
50 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
51 memcpy(rtap_data + offset, &info->signal, sizeof(info->signal));
52 offset += sizeof(info->signal);
53 break;
54 case IEEE80211_RADIOTAP_ANTENNA:
55 for (int i = 0; i < info->antenna_count; i++) {
56 memcpy(rtap_data + offset, &info->antennas->antenna_number,
57 sizeof(info->antennas->antenna_number));
58 offset += sizeof(info->antennas->antenna_number);
59 memcpy(rtap_data + offset, &info->antennas->signal, sizeof(info->antennas->signal));
60 offset += sizeof(info->antennas->signal);
61 }
62 break;
63 case IEEE80211_RADIOTAP_DBM_ANTNOISE:
64 break;
65 case IEEE80211_RADIOTAP_FLAGS:
66 memcpy(rtap_data + offset, &info->flags, sizeof(info->flags));
67 offset += sizeof(info->flags);
68 break;
69 case IEEE80211_RADIOTAP_EXT:
70 memcpy(rtap_data + offset, &info->extended_flags, sizeof(info->extended_flags));
71 offset += sizeof(info->extended_flags);
72 break;
73 case IEEE80211_RADIOTAP_RX_FLAGS:
74 memcpy(rtap_data + offset, &info->rx_flags, sizeof(info->rx_flags));
75 offset += sizeof(info->rx_flags);
76 break;
77 case IEEE80211_RADIOTAP_TX_FLAGS:
78 memcpy(rtap_data + offset, &info->tx_flags, sizeof(info->tx_flags));
79 offset += sizeof(info->tx_flags);
80 break;
81 case IEEE80211_RADIOTAP_MCS:
82 memcpy(rtap_data + offset, &info->mcs.known, sizeof(info->mcs.known));
83 offset += sizeof(info->mcs.known);
84 memcpy(rtap_data + offset, &info->mcs.flags, sizeof(info->mcs.flags));
85 offset += sizeof(info->mcs.flags);
86 memcpy(rtap_data + offset, &info->mcs.mcs, sizeof(info->mcs.mcs));
87 offset += sizeof(info->mcs.mcs);
88 break;
89 case IEEE80211_RADIOTAP_DBM_TX_POWER:
90 memcpy(rtap_data + offset, &info->tx_power, sizeof(info->tx_power));
91 offset += sizeof(info->tx_power);
92 break;
93 case IEEE80211_RADIOTAP_TIMESTAMP:
94 memcpy(rtap_data + offset, &info->timestamp.timestamp, sizeof(info->timestamp.timestamp));
95 offset += sizeof(info->timestamp.timestamp);
96 memcpy(rtap_data + offset, &info->timestamp.accuracy, sizeof(info->timestamp.accuracy));
97 offset += sizeof(info->timestamp.accuracy);
98 memcpy(rtap_data + offset, &info->timestamp.unit, sizeof(info->timestamp.unit));
99 offset += sizeof(info->timestamp.unit);
100 memcpy(rtap_data + offset, &info->timestamp.flags, sizeof(info->timestamp.flags));
101 offset += sizeof(info->timestamp.flags);
102 break;
103 case IEEE80211_RADIOTAP_RTS_RETRIES:
104 memcpy(rtap_data + offset, &info->rts_retries, sizeof(info->rts_retries));
105 offset += sizeof(info->rts_retries);
106 break;
107 case IEEE80211_RADIOTAP_DATA_RETRIES:
108 memcpy(rtap_data + offset, &info->data_retries, sizeof(info->data_retries));
109 offset += sizeof(info->data_retries);
110 break;
111 }
112 }
113
114 presence_bit >>= 1;
115 }
116
117 rtap_hdr.it_len += offset;
118
119 memcpy(radiotap_header, &rtap_hdr, sizeof(struct ieee80211_radiotap_header));
120 memcpy(radiotap_header + sizeof(struct ieee80211_radiotap_header), &rtap_data, offset);
121
122 return rtap_hdr.it_len;
123}
diff --git a/src/libwifi/gen/misc/radiotap.h b/src/libwifi/gen/misc/radiotap.h new file mode 100644 index 0000000..00e2ac8 --- /dev/null +++ b/src/libwifi/gen/misc/radiotap.h
@@ -0,0 +1,31 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_GEN_RADIOTAP_H
17#define LIBWIFI_GEN_RADIOTAP_H
18
19#include "../../core/misc/radiotap.h"
20#include <sys/types.h>
21
22/*
23 * Generate a customised radiotap header based on the input provided in info.
24 *
25 * @param info A libwifi_radiotap_info struct with desired radiotap data.
26 * @param radiotap_header Buffer to write the radiotap header into.
27 * @return Length of the generated radiotap header.
28 */
29size_t libwifi_create_radiotap(struct libwifi_radiotap_info *info, char *radiotap_header);
30
31#endif /* LIBWIFI_GEN_RADIOTAP_H */
diff --git a/src/libwifi/parse/data/data.c b/src/libwifi/parse/data/data.c new file mode 100644 index 0000000..74bff32 --- /dev/null +++ b/src/libwifi/parse/data/data.c
@@ -0,0 +1,48 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "data.h"
17
18#include <errno.h>
19#include <stdlib.h>
20#include <string.h>
21
22int libwifi_parse_data(struct libwifi_data *data, struct libwifi_frame *frame) {
23 if (frame->frame_control.type != TYPE_DATA) {
24 return -EINVAL;
25 }
26
27 if (frame->flags & LIBWIFI_FLAGS_IS_QOS) {
28 memcpy(data->receiver, frame->header.data_qos.addr1, 6);
29 memcpy(data->transmitter, frame->header.data_qos.addr2, 6);
30 } else {
31 memcpy(data->receiver, frame->header.data.addr1, 6);
32 memcpy(data->transmitter, frame->header.data.addr2, 6);
33 }
34
35 data->body_len = frame->len - frame->header_len;
36
37 data->body = malloc(data->body_len);
38 if (data->body == NULL) {
39 return -ENOMEM;
40 }
41 memcpy(frame->body, data->body, data->body_len);
42
43 return 0;
44}
45
46void libwifi_free_data(struct libwifi_data *data) {
47 free(data->body);
48}
diff --git a/src/libwifi/parse/data/data.h b/src/libwifi/parse/data/data.h new file mode 100644 index 0000000..3ed3bd4 --- /dev/null +++ b/src/libwifi/parse/data/data.h
@@ -0,0 +1,26 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_PARSE_DATA_H
17#define LIBWIFI_PARSE_DATA_H
18
19#include "../../core/frame/data/data.h"
20#include "../../core/frame/frame.h"
21
22int libwifi_parse_data(struct libwifi_data *data, struct libwifi_frame *frame);
23
24void libwifi_free_data(struct libwifi_data *data);
25
26#endif /* LIBWIFI_PARSE_DATA_H */
diff --git a/src/libwifi/parse/data/eapol.c b/src/libwifi/parse/data/eapol.c new file mode 100644 index 0000000..b8e3d18 --- /dev/null +++ b/src/libwifi/parse/data/eapol.c
@@ -0,0 +1,190 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "eapol.h"
17#include "../../core/frame/frame.h"
18#include "../../core/misc/byteswap.h"
19#include "../../core/misc/llc.h"
20#include "../../core/misc/security.h"
21
22#include <arpa/inet.h>
23#include <errno.h>
24#include <netinet/in.h>
25#include <stdlib.h>
26#include <string.h>
27
28/**
29 * A libwifi_frame is deemed to be an EAPOL handshake if the following criteria is met:
30 * - The frame is of type TYPE_DATA, and
31 * - The frame contains a logical link control layer, and
32 * - There is enough data in the frame body to fill a libwifi_wpa_auth_data struct.
33 */
34int libwifi_check_wpa_handshake(struct libwifi_frame *frame) {
35 // WPA Handshakes are transmitted in EAPOL frames
36 if (frame->frame_control.type != TYPE_DATA) {
37 return -EINVAL;
38 }
39
40 // Data frame must be at least the length of the header plus the encapsulating LLC
41 if (frame->len < (frame->header_len + sizeof(struct libwifi_logical_link_ctrl))) {
42 return -EINVAL;
43 }
44
45 // Represent the LLC layer so that we can check the OUI and ensure it is correct
46 struct libwifi_logical_link_ctrl *llc = (struct libwifi_logical_link_ctrl *) (frame->body);
47 if (memcmp(llc->oui, XEROX_OUI, sizeof(llc->oui)) != 0) {
48 return -EINVAL;
49 }
50
51 // Match the network byte-order of LLC and ensure we have a frame containing 802.1X information
52 if (ntohs(llc->type) != LLC_TYPE_AUTH) {
53 return -EINVAL;
54 }
55
56 // Ensure we have enough information in the frame to fill a libwifi_wpa_auth_data struct
57 // This value is calculated by ensuring the frame is at least the length of the LLC layer, plus the length
58 // of the libwifi_wpa_auth_data struct, however, the length of an unsigned char pointer is subtracted due
59 // to the possibility of the frame having no WPA key data.
60 size_t required_data_length =
61 frame->header_len + (sizeof(struct libwifi_logical_link_ctrl) +
62 (sizeof(struct libwifi_wpa_auth_data) - sizeof(unsigned char *)));
63 if (frame->len < required_data_length) {
64 return -EINVAL;
65 }
66
67 return 1;
68}
69
70/*
71 * The specific EAPOL message in the supplied libwifi_frame is determined via the 802.1X key information
72 * field.
73 */
74int libwifi_check_wpa_message(struct libwifi_frame *frame) {
75 // Ensure we have enough information in the frame to fill a libwifi_wpa_auth_data struct
76 // This value is calculated by ensuring the frame is at least the length of the LLC layer, plus the length
77 // of the libwifi_wpa_auth_data struct, however, the length of an unsigned char pointer is subtracted due
78 // to the possibility of the frame having no WPA key data.
79 size_t required_data_length =
80 frame->header_len + (sizeof(struct libwifi_logical_link_ctrl) +
81 (sizeof(struct libwifi_wpa_auth_data) - sizeof(unsigned char *)));
82 if (frame->len < required_data_length) {
83 return HANDSHAKE_INVALID;
84 }
85
86 struct libwifi_wpa_auth_data *auth_data =
87 (struct libwifi_wpa_auth_data *) (frame->body + sizeof(struct libwifi_logical_link_ctrl));
88 switch (ntohs(auth_data->key_info.information)) {
89 case EAPOL_KEY_INFO_M1:
90 return HANDSHAKE_M1;
91 case EAPOL_KEY_INFO_M2:
92 return HANDSHAKE_M2;
93 case EAPOL_KEY_INFO_M3:
94 return HANDSHAKE_M3;
95 case EAPOL_KEY_INFO_M4:
96 return HANDSHAKE_M4;
97 default:
98 return HANDSHAKE_INVALID;
99 }
100}
101
102/*
103 * Simple helper function to print a string depending on the EAPOL message
104 */
105const char *libwifi_get_wpa_message_string(struct libwifi_frame *frame) {
106 int message = libwifi_check_wpa_message(frame);
107
108 switch (message) {
109 case HANDSHAKE_M1:
110 return "Message 1";
111 case HANDSHAKE_M2:
112 return "Message 2";
113 case HANDSHAKE_M3:
114 return "Message 3";
115 case HANDSHAKE_M4:
116 return "Message 4";
117 case HANDSHAKE_INVALID:
118 default:
119 return "Invalid";
120 }
121}
122
123/*
124 * The value returned here is the length of the data available _after_ the rest of the EAPOL data,
125 * and should be used for obtaining the EAPOL Key Data, if present.
126 */
127int libwifi_get_wpa_key_data_length(struct libwifi_frame *frame) {
128 if (libwifi_check_wpa_handshake(frame) < 0) {
129 return -EINVAL;
130 }
131
132 struct libwifi_wpa_auth_data *auth_data =
133 (struct libwifi_wpa_auth_data *) (frame->body + sizeof(struct libwifi_logical_link_ctrl));
134
135 // Byte-swap the multi-byte length key_data_length for the host system
136 return ntohs(auth_data->key_info.key_data_length);
137}
138
139/*
140 * Data in the supplied libwifi_frame is expected to be in network byte order. To avoid confusion, this
141 * data is byte-swapped to the host system's endianess.
142 *
143 * If the supplied key_data is not NULL, any key data at the end of the frame will be written into the
144 * supplied key_data buffer. You can obtain the length to malloc such a buffer with
145 * libwifi_get_wpa_key_data_length.
146 */
147int libwifi_get_wpa_data(struct libwifi_frame *frame, struct libwifi_wpa_auth_data *data) {
148 memset(data, 0, sizeof(struct libwifi_wpa_auth_data));
149
150 if (libwifi_check_wpa_handshake(frame) < 0) {
151 return -EINVAL;
152 }
153
154 struct libwifi_wpa_auth_data *auth_data =
155 (struct libwifi_wpa_auth_data *) (frame->body + sizeof(struct libwifi_logical_link_ctrl));
156
157 // Multi-byte fields will be byte-swapped to the host byte order
158 data->version = auth_data->version;
159 data->type = auth_data->type;
160 data->length = ntohs(auth_data->length);
161 data->descriptor = auth_data->descriptor;
162 memcpy(&data->key_info, &auth_data->key_info, sizeof(struct libwifi_wpa_key_info));
163 data->key_info.information = ntohs(auth_data->key_info.information);
164 data->key_info.key_length = ntohs(auth_data->key_info.key_length);
165 data->key_info.replay_counter = be64toh(auth_data->key_info.replay_counter);
166 data->key_info.key_data_length = ntohs(auth_data->key_info.key_data_length);
167
168 if (data->key_info.key_data_length > 0) {
169 // Prevent huge allocations in corrupted or malicious frames
170 if (data->key_info.key_data_length > 1024) {
171 data->key_info.key_data_length = 1024;
172 }
173
174 data->key_info.key_data = malloc(data->key_info.key_data_length);
175 if (data->key_info.key_data == NULL) {
176 return -ENOMEM;
177 }
178 size_t key_data_offset = sizeof(struct libwifi_logical_link_ctrl) +
179 sizeof(struct libwifi_wpa_auth_data) - sizeof(unsigned char *);
180 memcpy(data->key_info.key_data, frame->body + key_data_offset, data->key_info.key_data_length);
181 }
182
183 return 0;
184}
185
186void libwifi_free_wpa_data(struct libwifi_wpa_auth_data *data) {
187 if (data->key_info.key_data_length > 0) {
188 free(data->key_info.key_data);
189 }
190}
diff --git a/src/libwifi/parse/data/eapol.h b/src/libwifi/parse/data/eapol.h new file mode 100644 index 0000000..08b7a35 --- /dev/null +++ b/src/libwifi/parse/data/eapol.h
@@ -0,0 +1,91 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_PARSE_EAPOL_H
17#define LIBWIFI_PARSE_EAPOL_H
18
19#include "../../core/frame/frame.h"
20#include "../../core/misc/security.h"
21
22enum WPA_HANDSHAKE_PART {
23 HANDSHAKE_M1 = 1,
24 HANDSHAKE_M2 = 2,
25 HANDSHAKE_M3 = 4,
26 HANDSHAKE_M4 = 8,
27 HANDSHAKE_INVALID = 16
28};
29
30/**
31 * Check if a libwifi_frame contains a WPA1/2 handshake message.
32 *
33 * @param libwifi_frame A libwifi_frame
34 * @return 1 if a handshake is detected, 0 if not.
35 */
36int libwifi_check_wpa_handshake(struct libwifi_frame *frame);
37
38/**
39 * Check what message of the WPA1/2 handshake is in the given frame.
40 *
41 * The returned value can be used with the WPA_HANDSHAKE_PART enum,
42 * such as:
43 *
44 * part = libwifi_check_wpa_message(frame);
45 * if (part & HANDSHAKE_M1) {
46 * // This is EAPOL Message 1
47 * }
48 *
49 * @param libwifi_frame A libwifi_frame
50 * @return A bitmask of parts.
51 */
52int libwifi_check_wpa_message(struct libwifi_frame *frame);
53
54/**
55 * Get a string describing the WPA handshake message inside a supplied libwifi_frame.
56 *
57 * @param libwifi_frame A libwifi_frame
58 * @return A string describing the WPA handshake message found
59 */
60const char *libwifi_get_wpa_message_string(struct libwifi_frame *frame);
61
62/**
63 * Get the length of the key data, if any, present at the end of an EAPOL frame.
64 *
65 * @param libwifi_frame A libwifi_frame
66 * @return The length of the key data
67 */
68int libwifi_get_wpa_key_data_length(struct libwifi_frame *frame);
69
70/**
71 * Get the EAPOL/WPA information from a given libwifi_frame.
72 *
73 * As the values in the frame below and including the logical link control layer will be in
74 * network byte order, the values will be automatically byte swapped if necessary to match
75 * the host systems byte order.
76 *
77 * @param libwifi_frame A libwifi_frame
78 * @param data A pointer to a libwifi_wpa_auth_data struct
79 * @return 0 on success, -1 on failure
80 */
81int libwifi_get_wpa_data(struct libwifi_frame *frame, struct libwifi_wpa_auth_data *data);
82
83/**
84 * Free any memory allocated inside of a libwifi_wpa_auth data, such as a buffer
85 * for WPA key data allocated by the library.
86 *
87 * @param data A pointer to a libwifi_wpa_auth_data struct
88 */
89void libwifi_free_wpa_data(struct libwifi_wpa_auth_data *data);
90
91#endif /* LIBWIFI_PARSE_EAPOL_H */
diff --git a/src/libwifi/parse/management/assoc_request.c b/src/libwifi/parse/management/assoc_request.c new file mode 100644 index 0000000..5e1f783 --- /dev/null +++ b/src/libwifi/parse/management/assoc_request.c
@@ -0,0 +1,79 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "assoc_request.h"
17#include "../../core/frame/tag_iterator.h"
18#include "common.h"
19
20#include <errno.h>
21#include <stdlib.h>
22#include <string.h>
23
24/**
25 * libwifi_parse_assoc_req will parse useful fields into a struct libwifi_sta.
26 *
27 * This function also checks to see if the transmitter address can be ANDed
28 * with 0x02, to determine a likelihood of randomized addresses.
29 *
30 * ┌─────────────────────────────────────────────┐
31 * │ Header (Ordered or Unordered) │ ── Association Request Header
32 * ├─────────────────────────────────────────────┤
33 * │ Fixed Parameters │ ─┐
34 * ├─────────────────────────────────────────────┤ ├── Association Request Body
35 * │ Tagged Parameters │ ─┘
36 * └─────────────────────────────────────────────┘
37 */
38int libwifi_parse_assoc_req(struct libwifi_sta *sta, struct libwifi_frame *frame) {
39 memset(sta, 0, sizeof(struct libwifi_sta));
40
41 if (frame->frame_control.type != TYPE_MANAGEMENT || frame->frame_control.subtype != SUBTYPE_ASSOC_REQ) {
42 return -EINVAL;
43 }
44
45 if (frame->frame_control.flags.ordered) {
46 memcpy(sta->transmitter, frame->header.mgmt_ordered.addr2, 6);
47 memcpy(sta->bssid, frame->header.mgmt_ordered.addr3, 6);
48 } else {
49 memcpy(sta->transmitter, frame->header.mgmt_unordered.addr2, 6);
50 memcpy(sta->bssid, frame->header.mgmt_unordered.addr3, 6);
51 }
52
53 if (sta->transmitter[0] & 0x02) {
54 sta->randomized = 1;
55 } else {
56 sta->randomized = 0;
57 }
58
59 // Fixed Parameters must be present
60 if (frame->len <= (frame->header_len + sizeof(struct libwifi_assoc_req_fixed_parameters))) {
61 return -EINVAL;
62 }
63
64 sta->tags.length = (frame->len - frame->header_len);
65 const unsigned char *tagged_params = frame->body;
66 sta->tags.parameters = malloc(sta->tags.length);
67 memcpy(sta->tags.parameters, tagged_params, sta->tags.length);
68
69 struct libwifi_tag_iterator it;
70 if (libwifi_tag_iterator_init(&it, sta->tags.parameters, sta->tags.length) != 0) {
71 return -EINVAL;
72 }
73
74 if (libwifi_sta_tag_parser(sta, &it) != 0) {
75 return -EINVAL;
76 }
77
78 return 0;
79}
diff --git a/src/libwifi/parse/management/assoc_request.h b/src/libwifi/parse/management/assoc_request.h new file mode 100644 index 0000000..2695711 --- /dev/null +++ b/src/libwifi/parse/management/assoc_request.h
@@ -0,0 +1,32 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_PARSE_ASSOCREQ_H
17#define LIBWIFI_PARSE_ASSOCREQ_H
18
19#include "../../core/frame/frame.h"
20#include "../../core/frame/management/assoc_request.h"
21#include "../../core/frame/management/common.h"
22
23/**
24 * Parse a association request into a libwifi_sta.
25 *
26 * @param sta A libwifi_sta
27 * @param frame A libwifi_frame
28 * @return 0 if successful, a negative number if not
29 */
30int libwifi_parse_assoc_req(struct libwifi_sta *sta, struct libwifi_frame *frame);
31
32#endif /* LIBWIFI_PARSE_ASSOCREQ_H */
diff --git a/src/libwifi/parse/management/assoc_response.c b/src/libwifi/parse/management/assoc_response.c new file mode 100644 index 0000000..27db560 --- /dev/null +++ b/src/libwifi/parse/management/assoc_response.c
@@ -0,0 +1,92 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "../../core/frame/management/assoc_response.h"
17#include "../../core/frame/frame.h"
18#include "../../core/frame/tag.h"
19#include "../../core/frame/tag_iterator.h"
20#include "../../core/misc/types.h"
21#include "../../parse/misc/security.h"
22#include "assoc_response.h"
23#include "common.h"
24
25#include <errno.h>
26#include <stdlib.h>
27#include <string.h>
28
29/**
30 * libwifi_parse_assoc_resp will parse useful information out of a Probe Response
31 * into a struct libwifi_bss. As Probe Response frames are very similar to Beacon
32 * frames, they can be treated in much the same way.
33 *
34 * ┌─────────────────────────────────────────────┐
35 * │ Header (Ordered or Unordered) │ ── Probe Response Header
36 * ├─────────────────────────────────────────────┤
37 * │ Fixed Parameters │ ─┐
38 * ├─────────────────────────────────────────────┤ ├── Probe Response Body
39 * │ Tagged Parameters │ ─┘
40 * └─────────────────────────────────────────────┘
41 */
42int libwifi_parse_assoc_resp(struct libwifi_bss *bss, struct libwifi_frame *frame) {
43 memset(bss, 0, sizeof(struct libwifi_bss));
44
45 if (frame->frame_control.type != TYPE_MANAGEMENT || frame->frame_control.subtype != SUBTYPE_ASSOC_RESP) {
46 return -EINVAL;
47 }
48
49 if (frame->frame_control.flags.ordered) {
50 memcpy(bss->receiver, frame->header.mgmt_ordered.addr1, 6);
51 memcpy(bss->transmitter, frame->header.mgmt_ordered.addr2, 6);
52 memcpy(bss->bssid, frame->header.mgmt_ordered.addr3, 6);
53 } else {
54 memcpy(bss->receiver, frame->header.mgmt_unordered.addr1, 6);
55 memcpy(bss->transmitter, frame->header.mgmt_unordered.addr2, 6);
56 memcpy(bss->bssid, frame->header.mgmt_unordered.addr3, 6);
57 }
58
59 // Fixed Parameters must be present
60 if (frame->len <= (frame->header_len + sizeof(struct libwifi_assoc_resp_fixed_parameters))) {
61 return -EINVAL;
62 }
63
64 // At least one Tagged Parameter must be present
65 if (frame->len < (frame->header_len + sizeof(struct libwifi_assoc_resp_fixed_parameters) + 2)) {
66 return -EINVAL;
67 }
68
69 struct libwifi_assoc_resp_fixed_parameters *fixed_params =
70 (struct libwifi_assoc_resp_fixed_parameters *) frame->body;
71 if (libwifi_check_capabilities(fixed_params->capabilities_information, CAPABILITIES_PRIVACY)) {
72 bss->encryption_info |= WEP;
73 }
74
75 bss->tags.length =
76 (frame->len - (frame->header_len + sizeof(struct libwifi_assoc_resp_fixed_parameters)));
77 const unsigned char *tagged_params = frame->body + sizeof(struct libwifi_assoc_resp_fixed_parameters);
78 bss->tags.parameters = malloc(bss->tags.length);
79 memcpy(bss->tags.parameters, tagged_params, bss->tags.length);
80
81 // Iterate through common BSS tagged parameters (WPA, RSN, etc)
82 struct libwifi_tag_iterator it;
83 memset(&it, 0, sizeof(struct libwifi_tag_iterator));
84 if (libwifi_tag_iterator_init(&it, bss->tags.parameters, bss->tags.length) != 0) {
85 return -EINVAL;
86 }
87 if (libwifi_bss_tag_parser(bss, &it) != 0) {
88 return -EINVAL;
89 };
90
91 return 0;
92}
diff --git a/src/libwifi/parse/management/assoc_response.h b/src/libwifi/parse/management/assoc_response.h new file mode 100644 index 0000000..142388d --- /dev/null +++ b/src/libwifi/parse/management/assoc_response.h
@@ -0,0 +1,35 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_PARSE_ASSOCRESP_H
17#define LIBWIFI_PARSE_ASSOCRESP_H
18
19#include <stdint.h>
20#include <sys/types.h>
21
22#include "../../core/frame/frame.h"
23#include "../../core/frame/management/common.h"
24#include "../../core/misc/security.h"
25
26/**
27 * Parse an association response frame into a libwifi_bss.
28 *
29 * @param bss A libwifi_bss
30 * @param frame A libwifi_frame
31 * @return 0 if successful, a negative number if not.
32 */
33int libwifi_parse_assoc_resp(struct libwifi_bss *bss, struct libwifi_frame *frame);
34
35#endif /* LIBWIFI_PARSE_ASSOCRESP_H */
diff --git a/src/libwifi/parse/management/beacon.c b/src/libwifi/parse/management/beacon.c new file mode 100644 index 0000000..bd36daf --- /dev/null +++ b/src/libwifi/parse/management/beacon.c
@@ -0,0 +1,91 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "../../core/frame/management/beacon.h"
17#include "../../core/frame/frame.h"
18#include "../../core/frame/tag.h"
19#include "../../core/frame/tag_iterator.h"
20#include "../../core/misc/types.h"
21#include "../../parse/misc/security.h"
22#include "beacon.h"
23#include "common.h"
24
25#include <errno.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29
30/**
31 * libwifi_parse_beacon will parse useful fields out of a supplied beacon frame
32 * in the format of a struct libwifi_frame.
33 *
34 * ┌─────────────────────────────────────────────┐
35 * │ Header (Ordered or Unordered) │ ── Beacon Header
36 * ├─────────────────────────────────────────────┤
37 * │ Fixed Parameters │ ─┐
38 * ├─────────────────────────────────────────────┤ ├── Beacon Body
39 * │ Tagged Parameters │ ─┘
40 * └─────────────────────────────────────────────┘
41 */
42int libwifi_parse_beacon(struct libwifi_bss *bss, struct libwifi_frame *frame) {
43 memset(bss, 0, sizeof(struct libwifi_bss));
44
45 if (frame->frame_control.type != TYPE_MANAGEMENT || frame->frame_control.subtype != SUBTYPE_BEACON) {
46 return -EINVAL;
47 }
48
49 if (frame->frame_control.flags.ordered) {
50 memcpy(bss->receiver, frame->header.mgmt_ordered.addr1, 6);
51 memcpy(bss->transmitter, frame->header.mgmt_ordered.addr2, 6);
52 memcpy(bss->bssid, frame->header.mgmt_ordered.addr3, 6);
53 } else {
54 memcpy(bss->receiver, frame->header.mgmt_unordered.addr1, 6);
55 memcpy(bss->transmitter, frame->header.mgmt_unordered.addr2, 6);
56 memcpy(bss->bssid, frame->header.mgmt_unordered.addr3, 6);
57 }
58
59 // Fixed Parameters must be present
60 if (frame->len <= (frame->header_len + sizeof(struct libwifi_beacon_fixed_parameters))) {
61 return -EINVAL;
62 }
63
64 // At least one Tagged Parameter must be present
65 if (frame->len < (frame->header_len + sizeof(struct libwifi_beacon_fixed_parameters) + 2)) {
66 return -EINVAL;
67 }
68
69 struct libwifi_beacon_fixed_parameters *fixed_params =
70 (struct libwifi_beacon_fixed_parameters *) frame->body;
71 if (libwifi_check_capabilities(fixed_params->capabilities_information, CAPABILITIES_PRIVACY)) {
72 bss->encryption_info |= WEP;
73 }
74
75 bss->tags.length = (frame->len - (frame->header_len + sizeof(struct libwifi_beacon_fixed_parameters)));
76 const unsigned char *tagged_params = frame->body + sizeof(struct libwifi_beacon_fixed_parameters);
77 bss->tags.parameters = malloc(bss->tags.length);
78 memcpy(bss->tags.parameters, tagged_params, bss->tags.length);
79
80 // Iterate through common BSS tagged parameters (WPA, RSN, etc)
81 struct libwifi_tag_iterator it;
82 memset(&it, 0, sizeof(struct libwifi_tag_iterator));
83 if (libwifi_tag_iterator_init(&it, bss->tags.parameters, bss->tags.length) != 0) {
84 return -EINVAL;
85 }
86 if (libwifi_bss_tag_parser(bss, &it) != 0) {
87 return -EINVAL;
88 };
89
90 return 0;
91}
diff --git a/src/libwifi/parse/management/beacon.h b/src/libwifi/parse/management/beacon.h new file mode 100644 index 0000000..8817d32 --- /dev/null +++ b/src/libwifi/parse/management/beacon.h
@@ -0,0 +1,35 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_PARSE_BEACON_H
17#define LIBWIFI_PARSE_BEACON_H
18
19#include <stdint.h>
20#include <sys/types.h>
21
22#include "../../core/frame/frame.h"
23#include "../../core/frame/management/common.h"
24#include "../../core/misc/security.h"
25
26/**
27 * Parse useful properties from a beacon frame into a libwifi_bss.
28 *
29 * @param bss A libwifi_bss
30 * @param frame A libwifi_frame
31 * @return 0 if successful, a negative number if not.
32 */
33int libwifi_parse_beacon(struct libwifi_bss *bss, struct libwifi_frame *frame);
34
35#endif /* LIBWIFI_PARSE_BEACON_H */
diff --git a/src/libwifi/parse/management/common.c b/src/libwifi/parse/management/common.c new file mode 100644 index 0000000..14d3d42 --- /dev/null +++ b/src/libwifi/parse/management/common.c
@@ -0,0 +1,192 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "common.h"
17#include "../../core/frame/tag.h"
18#include "../misc/security.h"
19
20#include <errno.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24
25/**
26 * Different implementations can have variations of hidden SSIDs.
27 * It is common to simply set the SSID to an empty string, but some
28 * devices may "blank" the real SSID without reducing the character count.
29 *
30 * Example: "My-SSID" -> "\x00\x00\x00\x00\x00\x00\x00"
31 */
32void libwifi_handle_ssid_tag(void *target, int target_type, const char *tag_data, int tag_len) {
33 int hidden = 0;
34 int null_ssid = 1;
35
36 if (tag_len <= 0) {
37 hidden = 1;
38 } else if (tag_len > 32) {
39 tag_len = 32;
40 }
41
42 for (int i = 0; i < tag_len; i++) {
43 if (memcmp(&tag_data[i], "\x00", 1) != 0) {
44 null_ssid = 0;
45 break;
46 }
47 }
48
49 if (null_ssid) {
50 hidden = 1;
51 }
52
53 if (target_type == LIBWIFI_BSS) {
54 struct libwifi_bss *bss = (struct libwifi_bss *) target;
55 memcpy(bss->ssid, tag_data, tag_len);
56 bss->hidden = hidden;
57 } else if (target_type == LIBWIFI_STA) {
58 struct libwifi_sta *sta = (struct libwifi_sta *) target;
59 memcpy(sta->ssid, tag_data, tag_len);
60 }
61}
62
63/**
64 * Handle the RSN Tagged Parameter.
65 *
66 * At the minimum, the required RSN data is the version and the group cipher suites.
67 * RSN information is then enumerated within the libwifi_get_rsn_info() function.
68 */
69int libwifi_bss_handle_rsn_tag(struct libwifi_bss *bss, const unsigned char *rsn_data, int rsn_len) {
70 struct libwifi_rsn_info rsn_info = {0};
71
72 bss->encryption_info &= ~(unsigned int) WEP;
73
74 int min_len = sizeof(rsn_info.rsn_version) + sizeof(struct libwifi_cipher_suite);
75 if (rsn_len < min_len) {
76 return -EINVAL;
77 }
78
79 const unsigned char *rsn_end = rsn_data + rsn_len;
80
81 if ((libwifi_get_rsn_info(&rsn_info, rsn_data, rsn_end) != 0)) {
82 return -EINVAL;
83 }
84
85 libwifi_enumerate_rsn_suites(&rsn_info, bss);
86
87 memcpy(&bss->rsn_info, &rsn_info, sizeof(struct libwifi_rsn_info));
88
89 return 0;
90}
91
92/**
93 * The Microsoft vendor tag is used to advertise WPA and WPS information, as well as
94 * some other features such as WMM/WME.
95 *
96 * The difference between the tags is found via the "Vendor Specific OUI Type" field.
97 * A common representation of this is XX:XX:XX:YY, such as 00:50:F2:04, where
98 * 00:50:F2 is the Microsoft OUI and 04 is the type.
99 *
100 * It is important to skip the OUI and Type as described above before parsing the data of
101 * the tag. This is encapsulated with the libwifi_tag_vendor_header struct.
102 */
103int libwifi_bss_handle_msft_tag(struct libwifi_bss *bss, const unsigned char *msft_data, int msft_len) {
104 struct libwifi_wpa_info wpa_info = {0};
105 struct libwifi_tag_vendor_header *vendor_header = (struct libwifi_tag_vendor_header *) msft_data;
106
107 switch (vendor_header->type) {
108 case MICROSOFT_OUI_TYPE_WPA:
109 bss->encryption_info &= ~(unsigned int) WEP;
110 bss->encryption_info |= WPA;
111
112 // Skip 4 bytes for the OUI (3) and Vendor Tag Type (1)
113 const unsigned char *wpa_data = msft_data + sizeof(struct libwifi_tag_vendor_header);
114 const unsigned char *wpa_end = msft_data + (msft_len + sizeof(struct libwifi_tag_vendor_header));
115
116 if ((libwifi_get_wpa_info(&wpa_info, wpa_data, wpa_end) != 0)) {
117 return -EINVAL;
118 }
119
120 libwifi_enumerate_wpa_suites(&wpa_info, bss);
121
122 memcpy(&bss->wpa_info, &wpa_info, sizeof(struct libwifi_wpa_info));
123 break;
124 case MICROSOFT_OUI_TYPE_WMM:
125 // WMM/WME Supported
126 break;
127 case MICROSOFT_OUI_TYPE_WPS:
128 bss->wps = 1;
129 break;
130 }
131
132 return 0;
133}
134
135/**
136 * This function is a parser for common and useful tags found in frames usually originating
137 * from the BSS. These include the SSID and DS or HT fields, which can be used to determine
138 * the channel.
139 */
140int libwifi_bss_tag_parser(struct libwifi_bss *bss, struct libwifi_tag_iterator *it) {
141 struct libwifi_tag_vendor_header *vendor_header = NULL;
142
143 do {
144 switch (it->tag_header->tag_num) {
145 case TAG_SSID:
146 libwifi_handle_ssid_tag((void *) bss, LIBWIFI_BSS, (const char *) it->tag_data,
147 it->tag_header->tag_len);
148 break;
149 case TAG_DS_PARAMETER:
150 case TAG_HT_OPERATION:
151 memcpy(&bss->channel, it->tag_data, 1);
152 break;
153 case TAG_RSN:
154 if ((libwifi_bss_handle_rsn_tag(bss, it->tag_data, it->tag_header->tag_len) != 0)) {
155 return -EINVAL;
156 };
157 break;
158 case TAG_VENDOR_SPECIFIC:
159 vendor_header = (struct libwifi_tag_vendor_header *) it->tag_data;
160
161 if (memcmp(vendor_header->oui, MICROSOFT_OUI, 3) == 0) {
162 if ((libwifi_bss_handle_msft_tag(bss, it->tag_data, it->tag_header->tag_len) != 0)) {
163 return -EINVAL;
164 }
165 }
166 break;
167 }
168 } while (libwifi_tag_iterator_next(it) != -1);
169
170 return 0;
171}
172
173/**
174 * This function is a parser for common and useful tags found in frames usually originating
175 * from the STA. These include the SSID and DS or HT fields, which can be used to determine
176 * the channel.
177 */
178int libwifi_sta_tag_parser(struct libwifi_sta *sta, struct libwifi_tag_iterator *it) {
179 do {
180 switch (it->tag_header->tag_num) {
181 case TAG_SSID:
182 libwifi_handle_ssid_tag(sta, LIBWIFI_STA, (const char *) it->tag_data,
183 it->tag_header->tag_len);
184 break;
185 case TAG_DS_PARAMETER:
186 memcpy(&sta->channel, it->tag_data, 1);
187 break;
188 }
189 } while (libwifi_tag_iterator_next(it) != -1);
190
191 return 0;
192}
diff --git a/src/libwifi/parse/management/common.h b/src/libwifi/parse/management/common.h new file mode 100644 index 0000000..ad6b1dc --- /dev/null +++ b/src/libwifi/parse/management/common.h
@@ -0,0 +1,70 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_PARSE_MGMT_COMMON_H
17#define LIBWIFI_PARSE_MGMT_COMMON_H
18
19#include "../../core/frame/management/common.h"
20#include "../../core/frame/tag_iterator.h"
21#include "../../core/misc/security.h"
22
23/**
24 * A helper function to set the SSID of a libwifi_bss, as well as check
25 * if it is hidden or not.
26 *
27 * @param target A libwifi_bss or libwifi_sta
28 * @param target_type LIBWIFI_BSS or LIBWIFI_STA
29 * @param ssid The SSID to set
30 * @param ssid_len The length of the supplied SSID
31 */
32void libwifi_handle_ssid_tag(void *target, int target_type, const char *ssid, int ssid_len);
33
34/**
35 * A helper function to handle the parsing of the RSN IE.
36 *
37 * @param bss A libwifi_bss
38 * @param rsn_data The RSN tag data
39 * @param rsn_len The length of the RSN tag data
40 */
41int libwifi_bss_handle_rsn_tag(struct libwifi_bss *bss, const unsigned char *rsn_data, int rsn_len);
42
43/**
44 * A helper function to handle the parsing of the Microsoft Vendor IE.
45 *
46 * @param bss A libwifi_bss
47 * @param msft_data The Microsoft vendor tag data
48 * @param msft_len The length of the Microsoft tag data
49 */
50int libwifi_bss_handle_msft_tag(struct libwifi_bss *bss, const unsigned char *msft_data, int msft_len);
51
52/**
53 * A helper function to iterate through common tags found in a libwifi_bss.
54 *
55 * @param bss A libwifi_bss
56 * @param it A libwifi_tag_iterator
57 * @return 0 if successful, a negative number if not
58 */
59int libwifi_bss_tag_parser(struct libwifi_bss *bss, struct libwifi_tag_iterator *it);
60
61/**
62 * A helper function to iterate through common tags found in a libwifi_sta.
63 *
64 * @param sta A libwifi_sta
65 * @param it A libwifi_tag_iterator
66 * @return 0 if successful, a negative number if not
67 */
68int libwifi_sta_tag_parser(struct libwifi_sta *sta, struct libwifi_tag_iterator *it);
69
70#endif /* LIBWIFI_PARSE_MGMT_COMMON_H */
diff --git a/src/libwifi/parse/management/deauthentication.c b/src/libwifi/parse/management/deauthentication.c new file mode 100644 index 0000000..1d976dc --- /dev/null +++ b/src/libwifi/parse/management/deauthentication.c
@@ -0,0 +1,74 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "deauthentication.h"
17#include "common.h"
18
19#include <errno.h>
20#include <stdlib.h>
21#include <string.h>
22
23/**
24 * TODO: potentally write a parsed_to_gen function that converts a parsed deauth back into
25 * something that can be passed directly into the interface?
26 */
27
28/**
29 * Deauthentication frames can originate from the BSS or the STA, with no way to know
30 * who sent the frame by looking at just the frame alone. Because of this, they are
31 * parsed into a struct libwifi_parsed_deauth instead of a libwifi_bss or libwifi_sta.
32 *
33 * ┌─────────────────────────────────────────────┐
34 * │ Header (Ordered or Unordered) │ ── Deauthentication Header
35 * ├─────────────────────────────────────────────┤
36 * │ Fixed Parameters │ ─┐
37 * ├─────────────────────────────────────────────┤ ├── Deauthentication Body
38 * │ Tagged Parameters │ ─┘
39 * └─────────────────────────────────────────────┘
40 */
41int libwifi_parse_deauth(struct libwifi_parsed_deauth *deauth, struct libwifi_frame *frame) {
42 memset(deauth, 0, sizeof(struct libwifi_parsed_deauth));
43
44 int tags_len = 0;
45
46 if (frame->frame_control.type != TYPE_MANAGEMENT || frame->frame_control.subtype != SUBTYPE_DEAUTH) {
47 return -EINVAL;
48 }
49
50 deauth->ordered = frame->frame_control.flags.ordered;
51
52 if (deauth->ordered) {
53 memcpy(&deauth->frame_header.ordered, &frame->header.mgmt_ordered,
54 sizeof(struct libwifi_mgmt_ordered_frame_header));
55 tags_len = (frame->len - sizeof(struct libwifi_mgmt_ordered_frame_header) -
56 sizeof(struct libwifi_deauth_fixed_parameters));
57 } else {
58 memcpy(&deauth->frame_header.unordered, &frame->header.mgmt_unordered,
59 sizeof(struct libwifi_mgmt_unordered_frame_header));
60 tags_len = (frame->len - sizeof(struct libwifi_mgmt_unordered_frame_header) -
61 sizeof(struct libwifi_deauth_fixed_parameters));
62 }
63
64 unsigned char *body = (unsigned char *) frame->body;
65
66 memcpy(&deauth->fixed_parameters, body, sizeof(struct libwifi_deauth_fixed_parameters));
67 body += sizeof(struct libwifi_deauth_fixed_parameters);
68
69 deauth->tags.parameters = malloc(tags_len);
70 memcpy(&deauth->tags.parameters, body, tags_len);
71 memcpy(&deauth->tags.length, &tags_len, sizeof(tags_len));
72
73 return 0;
74}
diff --git a/src/libwifi/parse/management/deauthentication.h b/src/libwifi/parse/management/deauthentication.h new file mode 100644 index 0000000..761e25c --- /dev/null +++ b/src/libwifi/parse/management/deauthentication.h
@@ -0,0 +1,25 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_PARSE_DEAUTH_H
17#define LIBWIFI_PARSE_DEAUTH_H
18
19#include "../../core/frame/frame.h"
20#include "../../core/frame/management/common.h"
21#include "../../core/frame/management/deauthentication.h"
22
23int libwifi_parse_deauth(struct libwifi_parsed_deauth *deauth, struct libwifi_frame *frame);
24
25#endif /* LIBWIFI_PARSE_DEAUTH_H */
diff --git a/src/libwifi/parse/management/disassociation.c b/src/libwifi/parse/management/disassociation.c new file mode 100644 index 0000000..2272066 --- /dev/null +++ b/src/libwifi/parse/management/disassociation.c
@@ -0,0 +1,72 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "disassociation.h"
17#include "common.h"
18
19#include <errno.h>
20#include <string.h>
21
22/**
23 * TODO: potentally write a parsed_to_gen function that converts a parsed disassoc back into
24 * something that can be passed directly into the interface?
25 */
26
27/**
28 * Disassociation frames can originate from the BSS or the STA, with no way to know
29 * who sent the frame by looking at just the frame alone. Because of this, they are
30 * parsed into a struct libwifi_parsed_deauth instead of a libwifi_bss or libwifi_sta.
31 *
32 * ┌─────────────────────────────────────────────┐
33 * │ Header (Ordered or Unordered) │ ── Disassociation Header
34 * ├─────────────────────────────────────────────┤
35 * │ Fixed Parameters │ ─┐
36 * ├─────────────────────────────────────────────┤ ├── Disassociation Body
37 * │ Tagged Parameters │ ─┘
38 * └─────────────────────────────────────────────┘
39 */
40int libwifi_parse_disassoc(struct libwifi_parsed_disassoc *disassoc, struct libwifi_frame *frame) {
41 memset(disassoc, 0, sizeof(struct libwifi_parsed_disassoc));
42
43 int tags_len = 0;
44
45 if (frame->frame_control.type != TYPE_MANAGEMENT || frame->frame_control.subtype != SUBTYPE_DISASSOC) {
46 return -EINVAL;
47 }
48
49 disassoc->ordered = frame->frame_control.flags.ordered;
50
51 if (disassoc->ordered) {
52 memcpy(&disassoc->frame_header.ordered, &frame->header.mgmt_ordered,
53 sizeof(struct libwifi_mgmt_ordered_frame_header));
54 tags_len = (frame->len - sizeof(struct libwifi_mgmt_ordered_frame_header) -
55 sizeof(struct libwifi_disassoc_fixed_parameters));
56 } else {
57 memcpy(&disassoc->frame_header.unordered, &frame->header.mgmt_unordered,
58 sizeof(struct libwifi_mgmt_unordered_frame_header));
59 tags_len = (frame->len - sizeof(struct libwifi_mgmt_unordered_frame_header) -
60 sizeof(struct libwifi_disassoc_fixed_parameters));
61 }
62
63 unsigned char *body = (unsigned char *) frame->body;
64
65 memcpy(&disassoc->fixed_parameters, body, sizeof(struct libwifi_disassoc_fixed_parameters));
66 body += sizeof(struct libwifi_disassoc_fixed_parameters);
67
68 memcpy(&disassoc->tags, body, tags_len);
69 body += tags_len;
70
71 return 0;
72}
diff --git a/src/libwifi/parse/management/disassociation.h b/src/libwifi/parse/management/disassociation.h new file mode 100644 index 0000000..dc9a086 --- /dev/null +++ b/src/libwifi/parse/management/disassociation.h
@@ -0,0 +1,25 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_PARSE_DISASSOC_H
17#define LIBWIFI_PARSE_DISASSOC_H
18
19#include "../../core/frame/frame.h"
20#include "../../core/frame/management/common.h"
21#include "../../core/frame/management/disassociation.h"
22
23int libwifi_parse_disassoc(struct libwifi_parsed_disassoc *disassoc, struct libwifi_frame *frame);
24
25#endif /* LIBWIFI_PARSE_DISASSOC_H */
diff --git a/src/libwifi/parse/management/probe_request.c b/src/libwifi/parse/management/probe_request.c new file mode 100644 index 0000000..7b3fadf --- /dev/null +++ b/src/libwifi/parse/management/probe_request.c
@@ -0,0 +1,72 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "probe_request.h"
17#include "../../core/frame/tag_iterator.h"
18#include "common.h"
19
20#include <errno.h>
21#include <stdlib.h>
22#include <string.h>
23
24/**
25 * libwifi_parse_probe_req will parse useful fields into a struct libwifi_sta.
26 *
27 * This function also checks to see if the transmitter address can be ANDed
28 * with 0x02, to determine a likelihood of randomized addresses.
29 *
30 * ┌─────────────────────────────────────────────┐
31 * │ Header (Ordered or Unordered) │ ── Probe Request Header
32 * ├─────────────────────────────────────────────┤
33 * │ Tagged Parameters │ ── Probe Request Body
34 * └─────────────────────────────────────────────┘
35 */
36int libwifi_parse_probe_req(struct libwifi_sta *sta, struct libwifi_frame *frame) {
37 memset(sta, 0, sizeof(struct libwifi_sta));
38
39 if (frame->frame_control.type != TYPE_MANAGEMENT || frame->frame_control.subtype != SUBTYPE_PROBE_REQ) {
40 return -EINVAL;
41 }
42
43 if (frame->frame_control.flags.ordered) {
44 memcpy(sta->transmitter, frame->header.mgmt_ordered.addr2, 6);
45 memcpy(sta->bssid, frame->header.mgmt_ordered.addr3, 6);
46 } else {
47 memcpy(sta->transmitter, frame->header.mgmt_unordered.addr2, 6);
48 memcpy(sta->bssid, frame->header.mgmt_unordered.addr3, 6);
49 }
50
51 if (sta->transmitter[0] & 0x02) {
52 sta->randomized = 1;
53 } else {
54 sta->randomized = 0;
55 }
56
57 sta->tags.length = (frame->len - frame->header_len);
58 const unsigned char *tagged_params = frame->body;
59 sta->tags.parameters = malloc(sta->tags.length);
60 memcpy(sta->tags.parameters, tagged_params, sta->tags.length);
61
62 struct libwifi_tag_iterator it;
63 if (libwifi_tag_iterator_init(&it, sta->tags.parameters, sta->tags.length) != 0) {
64 return -EINVAL;
65 }
66
67 if (libwifi_sta_tag_parser(sta, &it) != 0) {
68 return -EINVAL;
69 }
70
71 return 0;
72}
diff --git a/src/libwifi/parse/management/probe_request.h b/src/libwifi/parse/management/probe_request.h new file mode 100644 index 0000000..f318b2c --- /dev/null +++ b/src/libwifi/parse/management/probe_request.h
@@ -0,0 +1,32 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_PARSE_PROBEREQ_H
17#define LIBWIFI_PARSE_PROBEREQ_H
18
19#include "../../core/frame/frame.h"
20#include "../../core/frame/management/common.h"
21#include "../../core/frame/management/probe_request.h"
22
23/**
24 * Parse a probe request into a libwifi_sta.
25 *
26 * @param sta A libwifi_sta
27 * @param frame A libwifi_frame
28 * @return 0 if successful, a negative number if not
29 */
30int libwifi_parse_probe_req(struct libwifi_sta *sta, struct libwifi_frame *frame);
31
32#endif /* LIBWIFI_PARSE_PROBEREQ_H */
diff --git a/src/libwifi/parse/management/probe_response.c b/src/libwifi/parse/management/probe_response.c new file mode 100644 index 0000000..ed2e27f --- /dev/null +++ b/src/libwifi/parse/management/probe_response.c
@@ -0,0 +1,88 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "../../core/frame/management/probe_response.h"
17#include "../../core/frame/frame.h"
18#include "../../core/frame/tag.h"
19#include "../../core/frame/tag_iterator.h"
20#include "../../core/misc/types.h"
21#include "../../parse/misc/security.h"
22#include "common.h"
23#include "probe_response.h"
24
25#include <errno.h>
26#include <stdlib.h>
27#include <string.h>
28
29/**
30 * libwifi_parse_probe_resp will parse useful information out of a Probe Response
31 * into a struct libwifi_bss. As Probe Response frames are very similar to Beacon
32 * frames, they can be treated in much the same way.
33 *
34 * ┌─────────────────────────────────────────────┐
35 * │ Header (Ordered or Unordered) │ ── Probe Response Header
36 * ├─────────────────────────────────────────────┤
37 * │ Fixed Parameters │ ─┐
38 * ├─────────────────────────────────────────────┤ ├── Probe Response Body
39 * │ Tagged Parameters │ ─┘
40 * └─────────────────────────────────────────────┘
41 */
42int libwifi_parse_probe_resp(struct libwifi_bss *bss, struct libwifi_frame *frame) {
43 memset(bss, 0, sizeof(struct libwifi_bss));
44
45 if (frame->frame_control.type != TYPE_MANAGEMENT || frame->frame_control.subtype != SUBTYPE_PROBE_RESP) {
46 return -EINVAL;
47 }
48
49 if (frame->frame_control.flags.ordered) {
50 memcpy(bss->bssid, frame->header.mgmt_ordered.addr3, 6);
51 } else {
52 memcpy(bss->bssid, frame->header.mgmt_unordered.addr3, 6);
53 }
54
55 // Fixed Parameters must be present
56 if (frame->len <= (frame->header_len + sizeof(struct libwifi_probe_resp_fixed_parameters))) {
57 return -EINVAL;
58 }
59
60 // At least one Tagged Parameter must be present
61 if (frame->len < (frame->header_len + sizeof(struct libwifi_probe_resp_fixed_parameters) + 2)) {
62 return -EINVAL;
63 }
64
65 struct libwifi_probe_resp_fixed_parameters *fixed_params =
66 (struct libwifi_probe_resp_fixed_parameters *) frame->body;
67 if (libwifi_check_capabilities(fixed_params->capabilities_information, CAPABILITIES_PRIVACY)) {
68 bss->encryption_info |= WEP;
69 }
70
71 bss->tags.length =
72 (frame->len - (frame->header_len + sizeof(struct libwifi_probe_resp_fixed_parameters)));
73 const unsigned char *tagged_params = frame->body + sizeof(struct libwifi_probe_resp_fixed_parameters);
74 bss->tags.parameters = malloc(bss->tags.length);
75 memcpy(bss->tags.parameters, tagged_params, bss->tags.length);
76
77 // Iterate through common BSS tagged parameters (WPA, RSN, etc)
78 struct libwifi_tag_iterator it;
79 memset(&it, 0, sizeof(struct libwifi_tag_iterator));
80 if (libwifi_tag_iterator_init(&it, bss->tags.parameters, bss->tags.length) != 0) {
81 return -EINVAL;
82 }
83 if (libwifi_bss_tag_parser(bss, &it) != 0) {
84 return -EINVAL;
85 };
86
87 return 0;
88}
diff --git a/src/libwifi/parse/management/probe_response.h b/src/libwifi/parse/management/probe_response.h new file mode 100644 index 0000000..6810fed --- /dev/null +++ b/src/libwifi/parse/management/probe_response.h
@@ -0,0 +1,35 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_PARSE_PROBERESP_H
17#define LIBWIFI_PARSE_PROBERESP_H
18
19#include <stdint.h>
20#include <sys/types.h>
21
22#include "../../core/frame/frame.h"
23#include "../../core/frame/management/common.h"
24#include "../../core/misc/security.h"
25
26/**
27 * Parse a probe response frame into a libwifi_bss.
28 *
29 * @param bss A libwifi_bss
30 * @param frame A libwifi_frame
31 * @return 0 if successful, a negative number if not.
32 */
33int libwifi_parse_probe_resp(struct libwifi_bss *bss, struct libwifi_frame *frame);
34
35#endif /* LIBWIFI_PARSE_PROBERESP_H */
diff --git a/src/libwifi/parse/management/reassoc_request.c b/src/libwifi/parse/management/reassoc_request.c new file mode 100644 index 0000000..7c4f8ad --- /dev/null +++ b/src/libwifi/parse/management/reassoc_request.c
@@ -0,0 +1,79 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "reassoc_request.h"
17#include "../../core/frame/tag_iterator.h"
18#include "common.h"
19
20#include <errno.h>
21#include <stdlib.h>
22#include <string.h>
23
24/**
25 * libwifi_parse_reassoc_req will parse useful fields into a struct libwifi_sta.
26 *
27 * This function also checks to see if the transmitter address can be ANDed
28 * with 0x02, to determine a likelihood of randomized addresses.
29 *
30 * ┌─────────────────────────────────────────────┐
31 * │ Header (Ordered or Unordered) │ ── Ressociation Request Header
32 * ├─────────────────────────────────────────────┤
33 * │ Fixed Parameters │ ─┐
34 * ├─────────────────────────────────────────────┤ |── Ressociation Request Body
35 * │ Tagged Parameters │ ─┘
36 * └─────────────────────────────────────────────┘
37 */
38int libwifi_parse_reassoc_req(struct libwifi_sta *sta, struct libwifi_frame *frame) {
39 memset(sta, 0, sizeof(struct libwifi_sta));
40
41 if (frame->frame_control.type != TYPE_MANAGEMENT || frame->frame_control.subtype != SUBTYPE_REASSOC_REQ) {
42 return -EINVAL;
43 }
44
45 if (frame->frame_control.flags.ordered) {
46 memcpy(sta->transmitter, frame->header.mgmt_ordered.addr2, 6);
47 memcpy(sta->bssid, frame->header.mgmt_ordered.addr3, 6);
48 } else {
49 memcpy(sta->transmitter, frame->header.mgmt_unordered.addr2, 6);
50 memcpy(sta->bssid, frame->header.mgmt_unordered.addr3, 6);
51 }
52
53 if (sta->transmitter[0] & 0x02) {
54 sta->randomized = 1;
55 } else {
56 sta->randomized = 0;
57 }
58
59 // Fixed Parameters must be present
60 if (frame->len <= (frame->header_len + sizeof(struct libwifi_reassoc_req_fixed_parameters))) {
61 return -EINVAL;
62 }
63
64 sta->tags.length = (frame->len - frame->header_len);
65 const unsigned char *tagged_params = frame->body;
66 sta->tags.parameters = malloc(sta->tags.length);
67 memcpy(sta->tags.parameters, tagged_params, sta->tags.length);
68
69 struct libwifi_tag_iterator it;
70 if (libwifi_tag_iterator_init(&it, sta->tags.parameters, sta->tags.length) != 0) {
71 return -EINVAL;
72 }
73
74 if (libwifi_sta_tag_parser(sta, &it) != 0) {
75 return -EINVAL;
76 }
77
78 return 0;
79}
diff --git a/src/libwifi/parse/management/reassoc_request.h b/src/libwifi/parse/management/reassoc_request.h new file mode 100644 index 0000000..73e0c79 --- /dev/null +++ b/src/libwifi/parse/management/reassoc_request.h
@@ -0,0 +1,32 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_PARSE_REASSOCREQ_H
17#define LIBWIFI_PARSE_REASSOCREQ_H
18
19#include "../../core/frame/frame.h"
20#include "../../core/frame/management/common.h"
21#include "../../core/frame/management/reassoc_request.h"
22
23/**
24 * Parse a reassociation request into a libwifi_sta.
25 *
26 * @param sta A libwifi_sta
27 * @param frame A libwifi_frame
28 * @return 0 if successful, a negative number if not
29 */
30int libwifi_parse_reassoc_req(struct libwifi_sta *sta, struct libwifi_frame *frame);
31
32#endif /* LIBWIFI_PARSE_REASSOCREQ_H */
diff --git a/src/libwifi/parse/management/reassoc_response.c b/src/libwifi/parse/management/reassoc_response.c new file mode 100644 index 0000000..2c92827 --- /dev/null +++ b/src/libwifi/parse/management/reassoc_response.c
@@ -0,0 +1,92 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "../../core/frame/management/reassoc_response.h"
17#include "../../core/frame/frame.h"
18#include "../../core/frame/tag.h"
19#include "../../core/frame/tag_iterator.h"
20#include "../../core/misc/types.h"
21#include "../../parse/misc/security.h"
22#include "common.h"
23#include "reassoc_response.h"
24
25#include <errno.h>
26#include <stdlib.h>
27#include <string.h>
28
29/**
30 * libwifi_parse_reassoc_resp will parse useful information out of a Reassocation Response
31 * into a struct libwifi_bss.
32 *
33 * ┌─────────────────────────────────────────────┐
34 * │ Header (Ordered or Unordered) │ ── Reassocation Response Header
35 * ├─────────────────────────────────────────────┤
36 * │ Fixed Parameters │ ─┐
37 * ├─────────────────────────────────────────────┤ ├── Reassociation Response Body
38 * │ Tagged Parameters │ ─┘
39 * └─────────────────────────────────────────────┘
40 */
41int libwifi_parse_reassoc_resp(struct libwifi_bss *bss, struct libwifi_frame *frame) {
42 memset(bss, 0, sizeof(struct libwifi_bss));
43
44 if (frame->frame_control.type != TYPE_MANAGEMENT ||
45 frame->frame_control.subtype != SUBTYPE_REASSOC_RESP) {
46 return -EINVAL;
47 }
48
49 if (frame->frame_control.flags.ordered) {
50 memcpy(bss->receiver, frame->header.mgmt_ordered.addr1, 6);
51 memcpy(bss->transmitter, frame->header.mgmt_ordered.addr2, 6);
52 memcpy(bss->bssid, frame->header.mgmt_ordered.addr3, 6);
53 } else {
54 memcpy(bss->receiver, frame->header.mgmt_unordered.addr1, 6);
55 memcpy(bss->transmitter, frame->header.mgmt_unordered.addr2, 6);
56 memcpy(bss->bssid, frame->header.mgmt_unordered.addr3, 6);
57 }
58
59 // Fixed Parameters must be present
60 if (frame->len <= (frame->header_len + sizeof(struct libwifi_reassoc_resp_fixed_parameters))) {
61 return -EINVAL;
62 }
63
64 // At least one Tagged Parameter must be present
65 if (frame->len < (frame->header_len + sizeof(struct libwifi_reassoc_resp_fixed_parameters) + 2)) {
66 return -EINVAL;
67 }
68
69 struct libwifi_reassoc_resp_fixed_parameters *fixed_params =
70 (struct libwifi_reassoc_resp_fixed_parameters *) frame->body;
71 if (libwifi_check_capabilities(fixed_params->capabilities_information, CAPABILITIES_PRIVACY)) {
72 bss->encryption_info |= WEP;
73 }
74
75 bss->tags.length =
76 (frame->len - (frame->header_len + sizeof(struct libwifi_reassoc_resp_fixed_parameters)));
77 const unsigned char *tagged_params = frame->body + sizeof(struct libwifi_reassoc_resp_fixed_parameters);
78 bss->tags.parameters = malloc(bss->tags.length);
79 memcpy(bss->tags.parameters, tagged_params, bss->tags.length);
80
81 // Iterate through common BSS tagged parameters (WPA, RSN, etc)
82 struct libwifi_tag_iterator it;
83 memset(&it, 0, sizeof(struct libwifi_tag_iterator));
84 if (libwifi_tag_iterator_init(&it, bss->tags.parameters, bss->tags.length) != 0) {
85 return -EINVAL;
86 }
87 if (libwifi_bss_tag_parser(bss, &it) != 0) {
88 return -EINVAL;
89 };
90
91 return 0;
92}
diff --git a/src/libwifi/parse/management/reassoc_response.h b/src/libwifi/parse/management/reassoc_response.h new file mode 100644 index 0000000..ba14a6d --- /dev/null +++ b/src/libwifi/parse/management/reassoc_response.h
@@ -0,0 +1,35 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_PARSE_REASSOCRESP_H
17#define LIBWIFI_PARSE_REASSOCRESP_H
18
19#include <stdint.h>
20#include <sys/types.h>
21
22#include "../../core/frame/frame.h"
23#include "../../core/frame/management/common.h"
24#include "../../core/misc/security.h"
25
26/**
27 * Parse a reassociation response frame into a libwifi_bss.
28 *
29 * @param bss A libwifi_bss
30 * @param frame A libwifi_frame
31 * @return 0 if successful, a negative number if not.
32 */
33int libwifi_parse_reassoc_resp(struct libwifi_bss *bss, struct libwifi_frame *frame);
34
35#endif /* LIBWIFI_PARSE_REASSOCRESP_H */
diff --git a/src/libwifi/parse/misc/radiotap.c b/src/libwifi/parse/misc/radiotap.c new file mode 100644 index 0000000..176167e --- /dev/null +++ b/src/libwifi/parse/misc/radiotap.c
@@ -0,0 +1,126 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "radiotap.h"
17#include "../../core/radiotap/radiotap_iter.h"
18
19#include <endian.h>
20#include <stdint.h>
21
22/**
23 * The libwifi radiotap parser uses the usual ieee80211_radiotap_iterator to parse incoming
24 * radiotap headers into a consumable libwifi_radiotap_info struct.
25 */
26void libwifi_parse_radiotap_info(struct libwifi_radiotap_info *info, const unsigned char *frame) {
27 memset(info, 0, sizeof(struct libwifi_radiotap_info));
28
29 struct ieee80211_radiotap_header *rh = (struct ieee80211_radiotap_header *) frame;
30 struct ieee80211_radiotap_iterator it = {0};
31 int ret = ieee80211_radiotap_iterator_init(&it, (void *) frame, rh->it_len, NULL);
32
33 int skipped_antenna = 0;
34 info->length = rh->it_len;
35
36 while (!ret) {
37 switch (it.this_arg_index) {
38 case IEEE80211_RADIOTAP_CHANNEL:
39 info->channel.freq = le16toh(*(uint16_t *) it.this_arg);
40 info->channel.flags = le16toh(*(uint16_t *) (it.this_arg + 2));
41 break;
42 case IEEE80211_RADIOTAP_RATE:
43 info->rate_raw = *it.this_arg;
44 info->rate = (*it.this_arg / 2.0);
45 break;
46 case IEEE80211_RADIOTAP_DBM_ANTSIGNAL:
47 // Radiotap Headers will include the ANTSIGNAL without an explicit Antenna definition.
48 if (!skipped_antenna) {
49 info->signal = *it.this_arg;
50 skipped_antenna = 1;
51 break;
52 }
53
54 if (info->antenna_count < LIBWIFI_MAX_RADIOTAP_ANTENNAS) {
55 struct libwifi_radiotap_antenna antenna = {.antenna_number = info->antenna_count,
56 .signal = *it.this_arg};
57 info->antennas[info->antenna_count] = antenna;
58 info->antenna_count += 1;
59 }
60 break;
61 case IEEE80211_RADIOTAP_ANTENNA:
62 info->antennas[info->antenna_count - 1].antenna_number = *it.this_arg;
63 break;
64 case IEEE80211_RADIOTAP_DBM_ANTNOISE:
65 break;
66 case IEEE80211_RADIOTAP_FLAGS:
67 info->flags = *it.this_arg;
68 break;
69 case IEEE80211_RADIOTAP_EXT:
70 info->extended_flags = *it.this_arg;
71 break;
72 case IEEE80211_RADIOTAP_RX_FLAGS:
73 info->rx_flags = *it.this_arg;
74 break;
75 case IEEE80211_RADIOTAP_TX_FLAGS:
76 info->tx_flags = *it.this_arg;
77 break;
78 case IEEE80211_RADIOTAP_MCS:
79 info->mcs.known = *(uint8_t *) it.this_arg;
80 info->mcs.flags = *(uint8_t *) (it.this_arg + 2);
81 info->mcs.mcs = *(uint8_t *) (it.this_arg + 3);
82 break;
83 case IEEE80211_RADIOTAP_DBM_TX_POWER:
84 info->tx_power = *it.this_arg;
85 break;
86 case IEEE80211_RADIOTAP_TIMESTAMP:
87 info->timestamp.timestamp = le64toh(*(uint64_t *) it.this_arg);
88 info->timestamp.accuracy = le16toh(*(uint16_t *) (it.this_arg + 2));
89 info->timestamp.unit = *(uint8_t *) (it.this_arg + 3);
90 info->timestamp.flags = *(uint8_t *) (it.this_arg + 4);
91 break;
92 case IEEE80211_RADIOTAP_RTS_RETRIES:
93 info->rts_retries = *it.this_arg;
94 break;
95 case IEEE80211_RADIOTAP_DATA_RETRIES:
96 info->data_retries = *it.this_arg;
97 break;
98 }
99
100 ret = ieee80211_radiotap_iterator_next(&it);
101 }
102}
103
104/**
105 * A simpler function than the main libwifi_parse_radiotap_info function, designed to extract
106 * only the signal strength field.
107 */
108int8_t libwifi_parse_radiotap_rssi(const unsigned char *frame) {
109 struct ieee80211_radiotap_header *rh = (struct ieee80211_radiotap_header *) frame;
110
111 int8_t rssi = 0;
112
113 struct ieee80211_radiotap_iterator it;
114 int ret = ieee80211_radiotap_iterator_init(&it, (void *) frame, rh->it_len, NULL);
115
116 while (!ret) {
117 if (it.this_arg_index == IEEE80211_RADIOTAP_DBM_ANTSIGNAL) {
118 rssi = *it.this_arg;
119 break;
120 }
121
122 ret = ieee80211_radiotap_iterator_next(&it);
123 }
124
125 return rssi;
126}
diff --git a/src/libwifi/parse/misc/radiotap.h b/src/libwifi/parse/misc/radiotap.h new file mode 100644 index 0000000..8f74e6a --- /dev/null +++ b/src/libwifi/parse/misc/radiotap.h
@@ -0,0 +1,39 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_PARSE_RADIOTAP_H
17#define LIBWIFI_PARSE_RADIOTAP_H
18
19#include "../../core/misc/radiotap.h"
20#include <stdint.h>
21
22/**
23 * Parse the radiotap information out of a raw frame into a
24 * libwifi_radiotap_info.
25 *
26 * @param info A libwifi_radiotap_info
27 * @param frame A raw 802.11 frame
28 */
29void libwifi_parse_radiotap_info(struct libwifi_radiotap_info *info, const unsigned char *frame);
30
31/**
32 * Retrieve the signal strength from a raw frame via radiotap header.
33 *
34 * @param frame A raw 802.11 frame
35 * @return signal strength in dBm
36 */
37int8_t libwifi_parse_radiotap_rssi(const unsigned char *frame);
38
39#endif /* LIBWIFI_PARSE_RADIOTAP_H */
diff --git a/src/libwifi/parse/misc/security.c b/src/libwifi/parse/misc/security.c new file mode 100644 index 0000000..bf211f7 --- /dev/null +++ b/src/libwifi/parse/misc/security.c
@@ -0,0 +1,685 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include "security.h"
17#include "../../core/misc/byteswap.h"
18
19#include <errno.h>
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23
24/**
25 * RSN Information is supplied via the raw tag data. The supplied data is then "walked"
26 * through as a pointer to extract the details of the tag and write them into
27 * a struct libwifi_rsn_info.
28 *
29 * libwifi supports a maximum of 3 Pairwise Cipher Suites and 3 Auth Key Management Suites.
30 * The Version, Group Cipher Suite and Capabilities fields are all required.
31 */
32int libwifi_get_rsn_info(struct libwifi_rsn_info *info, const unsigned char *tag_data,
33 const unsigned char *tag_end) {
34 memset(info, 0, sizeof(struct libwifi_rsn_info));
35
36 // Create a pointer we can manipulate from the tag data
37 unsigned char *data = (unsigned char *) tag_data;
38
39 // Handle the RSN Version
40 memcpy(&info->rsn_version, data, sizeof(info->rsn_version));
41 data += sizeof(info->rsn_version);
42
43 // Handle the RSN Group Cipher Suites
44 memcpy(&info->group_cipher_suite, data, sizeof(struct libwifi_cipher_suite));
45 data += sizeof(struct libwifi_cipher_suite);
46
47 // Bounds check and handle the RSN Pairwise Ciphers
48 if (data > tag_end) {
49 return -EINVAL;
50 }
51 if ((data + sizeof(uint16_t)) > tag_end) {
52 return -EINVAL;
53 }
54 uint16_t suite_count = *data;
55 if (suite_count > LIBWIFI_MAX_CIPHER_SUITES) {
56 suite_count = LIBWIFI_MAX_CIPHER_SUITES;
57 }
58 data += sizeof(suite_count);
59 if ((((suite_count * sizeof(struct libwifi_cipher_suite)) + data)) > tag_end) {
60 return -EINVAL;
61 }
62 info->num_pairwise_cipher_suites = suite_count;
63
64 // Iterate through the found Pairwise Ciphers, adding them each time
65 struct wifi_cipher_suite *cur_cipher_suite = NULL;
66 for (int i = 0; i < suite_count; ++i) {
67 if (data > tag_end) {
68 return -EINVAL;
69 }
70 cur_cipher_suite = (struct wifi_cipher_suite *) data;
71 memcpy(&info->pairwise_cipher_suites[i], cur_cipher_suite, sizeof(struct libwifi_cipher_suite));
72 info->pairwise_cipher_suites[i].suite_type = info->pairwise_cipher_suites[i].suite_type;
73 data += sizeof(struct libwifi_cipher_suite);
74 }
75
76 // Bounds check and handle the RSN Authentication Key Management Suites
77 if ((data + sizeof(suite_count)) > tag_end) {
78 return -EINVAL;
79 }
80 suite_count = *data;
81 if (suite_count > LIBWIFI_MAX_CIPHER_SUITES) {
82 suite_count = LIBWIFI_MAX_CIPHER_SUITES;
83 }
84 data += sizeof(suite_count);
85 if ((((suite_count * sizeof(struct libwifi_cipher_suite)) + data)) > tag_end) {
86 return -EINVAL;
87 }
88 info->num_auth_key_mgmt_suites = suite_count;
89
90 // Iterate through the found Auth Key Management Suites, adding them each time
91 for (int i = 0; i < suite_count; ++i) {
92 if (data > tag_end) {
93 return -EINVAL;
94 }
95 cur_cipher_suite = (struct wifi_cipher_suite *) data;
96 memcpy(&info->auth_key_mgmt_suites[i], cur_cipher_suite, sizeof(struct libwifi_cipher_suite));
97 info->auth_key_mgmt_suites[i].suite_type = info->auth_key_mgmt_suites[i].suite_type;
98 data += sizeof(struct libwifi_cipher_suite);
99 }
100
101 // Bounds check and handle the RSN Capabilities field
102 if (data > tag_end) {
103 return -EINVAL;
104 }
105 memcpy(&info->rsn_capabilities, data, sizeof(info->rsn_capabilities));
106
107 return 0;
108}
109
110/**
111 * This function will enumerate over a supplied struct libwifi_rsn_info and write
112 * the following into a supplied struct libwifi_bss:
113 *
114 * - Group Cipher Suite
115 * - Up to 3 Pairwise Cipher Suites
116 * - Up to 3 Auth Key Management Suites
117 * - The WPA Type (WPA2 or WPA3)
118 *
119 * The bss->encryption_info field is a 64-bit wide bitmask. The larger length is
120 * required to accomodate the different types of cipher suites without having
121 * any overlap between group cipher and pairwise cipher.
122 */
123void libwifi_enumerate_rsn_suites(struct libwifi_rsn_info *rsn_info, struct libwifi_bss *bss) {
124 switch (rsn_info->group_cipher_suite.suite_type) {
125 case CIPHER_SUITE_WEP40:
126 bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_WEP40;
127 break;
128 case CIPHER_SUITE_TKIP:
129 bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_TKIP;
130 break;
131 case CIPHER_SUITE_RESERVED:
132 bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_RESERVED;
133 break;
134 case CIPHER_SUITE_CCMP128:
135 bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_CCMP128;
136 break;
137 case CIPHER_SUITE_WEP104:
138 bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_WEP104;
139 break;
140 case CIPHER_SUITE_BIP_CMAC128:
141 bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_BIP_CMAC128;
142 break;
143 case CIPHER_SUITE_NOTALLOWED:
144 bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_NOTALLOWED;
145 break;
146 case CIPHER_SUITE_GCMP128:
147 bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_GCMP128;
148 break;
149 case CIPHER_SUITE_GCMP256:
150 bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_GCMP256;
151 break;
152 case CIPHER_SUITE_CCMP256:
153 bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_CCMP256;
154 break;
155 case CIPHER_SUITE_BIP_GMAC128:
156 bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_BIP_GMAC128;
157 break;
158 case CIPHER_SUITE_BIP_GMAC256:
159 bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_BIP_GMAC256;
160 break;
161 case CIPHER_SUITE_BIP_CMAC256:
162 bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_BIP_CMAC256;
163 break;
164 default:
165 break;
166 }
167
168 for (int i = 0; i < rsn_info->num_pairwise_cipher_suites; ++i) {
169 if ((memcmp(rsn_info->pairwise_cipher_suites[i].oui, CIPHER_SUITE_OUI, 3) == 0)) {
170 switch (rsn_info->pairwise_cipher_suites[i].suite_type) {
171 case CIPHER_SUITE_GROUP:
172 bss->encryption_info |= LIBWIFI_PAIRWISE_SUITE_GROUP;
173 break;
174 case CIPHER_SUITE_TKIP:
175 bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_TKIP;
176 break;
177 case CIPHER_SUITE_RESERVED:
178 bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_RESERVED;
179 break;
180 case CIPHER_SUITE_CCMP128:
181 bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_CCMP128;
182 break;
183 case CIPHER_SUITE_BIP_CMAC128:
184 bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_CMAC128;
185 break;
186 case CIPHER_SUITE_NOTALLOWED:
187 bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_NOTALLOWED;
188 break;
189 case CIPHER_SUITE_GCMP128:
190 bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_GCMP128;
191 break;
192 case CIPHER_SUITE_GCMP256:
193 bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_GCMP256;
194 break;
195 case CIPHER_SUITE_CCMP256:
196 bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_CCMP256;
197 break;
198 case CIPHER_SUITE_BIP_GMAC128:
199 bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_GMAC128;
200 break;
201 case CIPHER_SUITE_BIP_GMAC256:
202 bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_GMAC256;
203 break;
204 case CIPHER_SUITE_BIP_CMAC256:
205 bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_CMAC256;
206 break;
207 default:
208 break;
209 }
210 }
211 }
212
213 for (int i = 0; i < rsn_info->num_auth_key_mgmt_suites; ++i) {
214 if (memcmp(rsn_info->auth_key_mgmt_suites[i].oui, CIPHER_SUITE_OUI, 3) == 0) {
215 switch (rsn_info->auth_key_mgmt_suites[i].suite_type) {
216 case AKM_SUITE_RESERVED:
217 bss->encryption_info |= WPA2;
218 bss->encryption_info |= LIBWIFI_AKM_SUITE_RESERVED;
219 break;
220 case AKM_SUITE_1X:
221 bss->encryption_info |= WPA2;
222 bss->encryption_info |= LIBWIFI_AKM_SUITE_1X;
223 break;
224 case AKM_SUITE_PSK:
225 bss->encryption_info |= WPA2;
226 bss->encryption_info |= LIBWIFI_AKM_SUITE_PSK;
227 break;
228 case AKM_SUITE_1X_FT:
229 bss->encryption_info |= WPA2;
230 bss->encryption_info |= LIBWIFI_AKM_SUITE_1X_FT;
231 break;
232 case AKM_SUITE_PSK_FT:
233 bss->encryption_info |= WPA2;
234 bss->encryption_info |= LIBWIFI_AKM_SUITE_PSK_FT;
235 break;
236 case AKM_SUITE_1X_SHA256:
237 bss->encryption_info |= WPA2;
238 bss->encryption_info |= LIBWIFI_AKM_SUITE_1X_SHA256;
239 break;
240 case AKM_SUITE_PSK_SHA256:
241 bss->encryption_info |= WPA2;
242 bss->encryption_info |= LIBWIFI_AKM_SUITE_PSK_SHA256;
243 break;
244 case AKM_SUITE_TDLS:
245 bss->encryption_info |= WPA2;
246 bss->encryption_info |= LIBWIFI_AKM_SUITE_TDLS;
247 break;
248 case AKM_SUITE_SAE:
249 bss->encryption_info |= WPA3;
250 bss->encryption_info |= LIBWIFI_AKM_SUITE_SAE;
251 break;
252 case AKM_SUITE_SAE_FT:
253 bss->encryption_info |= WPA3;
254 bss->encryption_info |= LIBWIFI_AKM_SUITE_SAE_FT;
255 break;
256 case AKM_SUITE_AP_PEER:
257 bss->encryption_info |= WPA3;
258 bss->encryption_info |= LIBWIFI_AKM_SUITE_AP_PEER;
259 break;
260 case AKM_SUITE_1X_SUITEB_SHA256:
261 bss->encryption_info |= WPA3;
262 bss->encryption_info |= LIBWIFI_AKM_SUITE_1X_SUITEB_SHA256;
263 break;
264 case AKM_SUITE_1X_SUITEB_SHA384:
265 bss->encryption_info |= WPA3;
266 bss->encryption_info |= LIBWIFI_AKM_SUITE_1X_SUITEB_SHA384;
267 break;
268 case AKM_SUITE_1X_FT_SHA384:
269 bss->encryption_info |= WPA3;
270 bss->encryption_info |= LIBWIFI_AKM_SUITE_1X_FT_SHA384;
271 break;
272 case AKM_SUITE_FILS_SHA256:
273 bss->encryption_info |= WPA2;
274 bss->encryption_info |= LIBWIFI_AKM_SUITE_FILS_SHA256;
275 break;
276 case AKM_SUITE_FILS_SHA384:
277 bss->encryption_info |= WPA3;
278 bss->encryption_info |= LIBWIFI_AKM_SUITE_FILS_SHA384;
279 break;
280 case AKM_SUITE_FILS_SHA256_FT:
281 bss->encryption_info |= WPA2;
282 bss->encryption_info |= LIBWIFI_AKM_SUITE_FILS_SHA256_FT;
283 break;
284 case AKM_SUITE_FILS_SHA384_FT:
285 bss->encryption_info |= WPA3;
286 bss->encryption_info |= LIBWIFI_AKM_SUITE_FILS_SHA384_FT;
287 break;
288 case AKM_SUITE_OWE:
289 bss->encryption_info |= WPA3;
290 bss->encryption_info |= LIBWIFI_AKM_SUITE_OWE;
291 break;
292 case AKM_PSK_SHA384_FT:
293 bss->encryption_info |= WPA3;
294 bss->encryption_info |= LIBWIFI_AKM_PSK_SHA384_FT;
295 break;
296 case AKM_PSK_SHA384:
297 bss->encryption_info |= WPA3;
298 bss->encryption_info |= LIBWIFI_AKM_PSK_SHA384;
299 break;
300 default:
301 break;
302 }
303 }
304 }
305}
306
307/**
308 * Similar to libwifi_get_rsn_info, WPA Information is supplied via the raw tag data.
309 * The supplied data is then "walked" through as a pointer to extract the details of
310 * the tag and write them into a struct libwifi_wpa_info.
311 *
312 * libwifi supports a maximum of 3 Unicast Cipher Suites and 3 Auth Key Management Suites.
313 * The Version and Multicast Cipher Suite fields are required.
314 */
315int libwifi_get_wpa_info(struct libwifi_wpa_info *info, const unsigned char *tag_data,
316 const unsigned char *tag_end) {
317 memset(info, 0, sizeof(struct libwifi_wpa_info));
318
319 // Create a pointer we can manipulate from the tag data
320 unsigned char *data = ((unsigned char *) tag_data);
321
322 // Handle the WPA Version
323 memcpy(&info->wpa_version, data, sizeof(info->wpa_version));
324 data += sizeof(info->wpa_version);
325
326 // Handle the WPA Multicast Cipher Suite
327 memcpy(&info->multicast_cipher_suite, data, sizeof(struct libwifi_cipher_suite));
328 data += sizeof(struct libwifi_cipher_suite);
329
330 // Bounds check and handle the WPA Unicast Cipher Suites
331 if (data > tag_end) {
332 return -EINVAL;
333 }
334 if ((data + sizeof(uint16_t)) > tag_end) {
335 return -EINVAL;
336 }
337 uint16_t suite_count = *data;
338 if (suite_count > LIBWIFI_MAX_CIPHER_SUITES) {
339 suite_count = LIBWIFI_MAX_CIPHER_SUITES;
340 }
341 data += sizeof(suite_count);
342 if ((((suite_count * sizeof(struct libwifi_cipher_suite)) + data)) > tag_end) {
343 return -EINVAL;
344 }
345 info->num_unicast_cipher_suites = suite_count;
346
347 // Iterate through the found Unicast Ciphers, adding them each time
348 struct wifi_cipher_suite *cur_cipher_suite = NULL;
349 for (int i = 0; i < suite_count; ++i) {
350 if (data > tag_end) {
351 return -EINVAL;
352 }
353 cur_cipher_suite = (struct wifi_cipher_suite *) data;
354 memcpy(&info->unicast_cipher_suites[i], cur_cipher_suite, sizeof(struct libwifi_cipher_suite));
355 info->unicast_cipher_suites[i].suite_type = info->unicast_cipher_suites[i].suite_type;
356 data += sizeof(struct libwifi_cipher_suite);
357 }
358
359 // Bounds check and handle the WPA Authentication Key Management Suites
360 if ((data + sizeof(suite_count)) > tag_end) {
361 return -EINVAL;
362 }
363 suite_count = *data;
364 if (suite_count > LIBWIFI_MAX_CIPHER_SUITES) {
365 suite_count = LIBWIFI_MAX_CIPHER_SUITES;
366 }
367 data += sizeof(suite_count);
368 if ((((suite_count * sizeof(struct libwifi_cipher_suite)) + data)) > tag_end) {
369 return -EINVAL;
370 }
371 info->num_auth_key_mgmt_suites = suite_count;
372
373 // Iterate through the found Auth Key Management Suites, adding them each time
374 for (int i = 0; i < suite_count; ++i) {
375 if (data > tag_end) {
376 return -EINVAL;
377 }
378 cur_cipher_suite = (struct wifi_cipher_suite *) data;
379 memcpy(&info->auth_key_mgmt_suites[i], cur_cipher_suite, sizeof(struct libwifi_cipher_suite));
380 info->auth_key_mgmt_suites[i].suite_type = info->auth_key_mgmt_suites[i].suite_type;
381 data += sizeof(struct libwifi_cipher_suite);
382 }
383
384 return 0;
385}
386
387/**
388 * Similarly to libwifi_enumerate_wpa_suites, this function will enumerate over a supplied
389 * struct libwifi_wpa_info and write the following into a supplied struct libwifi_bss:
390 *
391 * - Multicast Cipher Suite
392 * - Up to 3 Unicast Cipher Suites
393 * - Up to 3 Auth Key Management Suites
394 *
395 * The bss->encryption_info field is a 64-bit wide bitmask. The larger length is
396 * required to accomodate the different types of cipher suites without having
397 * any overlap between group cipher and pairwise cipher.
398 */
399void libwifi_enumerate_wpa_suites(struct libwifi_wpa_info *wpa_info, struct libwifi_bss *bss) {
400 switch (wpa_info->multicast_cipher_suite.suite_type) {
401 case CIPHER_SUITE_WEP40:
402 bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_WEP40;
403 break;
404 case CIPHER_SUITE_WEP104:
405 bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_WEP104;
406 break;
407 case CIPHER_SUITE_TKIP:
408 bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_TKIP;
409 break;
410 case CIPHER_SUITE_RESERVED:
411 bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_RESERVED;
412 break;
413 default:
414 break;
415 }
416
417 for (int i = 0; i < wpa_info->num_unicast_cipher_suites; ++i) {
418 if ((memcmp(wpa_info->unicast_cipher_suites[i].oui, MICROSOFT_OUI, 3) == 0)) {
419 switch (wpa_info->unicast_cipher_suites[i].suite_type) {
420 case CIPHER_SUITE_GROUP:
421 bss->encryption_info |= LIBWIFI_PAIRWISE_SUITE_GROUP;
422 break;
423 case CIPHER_SUITE_TKIP:
424 bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_TKIP;
425 break;
426 case CIPHER_SUITE_RESERVED:
427 bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_RESERVED;
428 break;
429 case CIPHER_SUITE_WEP40:
430 bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_WEP40;
431 break;
432 case CIPHER_SUITE_WEP104:
433 bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_WEP104;
434 break;
435 default:
436 break;
437 }
438 }
439 }
440
441 for (int i = 0; i < wpa_info->num_auth_key_mgmt_suites; ++i) {
442 if (memcmp(wpa_info->auth_key_mgmt_suites[i].oui, MICROSOFT_OUI, 3) == 0) {
443 switch (wpa_info->auth_key_mgmt_suites[i].suite_type) {
444 case AKM_SUITE_RESERVED:
445 bss->encryption_info |= WPA;
446 bss->encryption_info |= LIBWIFI_AKM_SUITE_RESERVED;
447 break;
448 case AKM_SUITE_1X:
449 bss->encryption_info |= WPA;
450 bss->encryption_info |= LIBWIFI_AKM_SUITE_1X;
451 break;
452 case AKM_SUITE_PSK:
453 bss->encryption_info |= WPA;
454 bss->encryption_info |= LIBWIFI_AKM_SUITE_PSK;
455 break;
456 case AKM_SUITE_1X_FT:
457 bss->encryption_info |= WPA;
458 bss->encryption_info |= LIBWIFI_AKM_SUITE_1X_FT;
459 break;
460 case AKM_SUITE_PSK_FT:
461 bss->encryption_info |= WPA;
462 bss->encryption_info |= LIBWIFI_AKM_SUITE_PSK_FT;
463 break;
464 }
465 }
466 }
467}
468
469void libwifi_get_security_type(struct libwifi_bss *bss, char *buf) {
470 memset(buf, 0, LIBWIFI_SECURITY_BUF_LEN);
471
472 int offset = 0;
473 int append = 0;
474
475 if (bss->encryption_info == 0) {
476 snprintf(buf, LIBWIFI_SECURITY_BUF_LEN, "None");
477 return;
478 }
479
480 if (bss->encryption_info & WPA3) {
481 _libwifi_add_sec_item(buf, &offset, &append, "WPA3");
482 }
483 if (bss->encryption_info & WPA2) {
484 _libwifi_add_sec_item(buf, &offset, &append, "WPA2");
485 }
486 if (bss->encryption_info & WPA) {
487 _libwifi_add_sec_item(buf, &offset, &append, "WPA");
488 }
489 if (bss->encryption_info & WEP) {
490 _libwifi_add_sec_item(buf, &offset, &append, "WEP");
491 }
492}
493
494void libwifi_get_group_ciphers(struct libwifi_bss *bss, char *buf) {
495 memset(buf, 0, LIBWIFI_SECURITY_BUF_LEN);
496
497 int offset = 0;
498 int append = 0;
499
500 if (bss->encryption_info == 0) {
501 snprintf(buf + offset, LIBWIFI_SECURITY_BUF_LEN, "None");
502 return;
503 }
504
505 if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_WEP40) {
506 _libwifi_add_sec_item(buf, &offset, &append, "WEP40");
507 }
508 if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_TKIP) {
509 _libwifi_add_sec_item(buf, &offset, &append, "TKIP");
510 }
511 if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_RESERVED) {
512 _libwifi_add_sec_item(buf, &offset, &append, "RESERVED");
513 }
514 if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_CCMP128) {
515 _libwifi_add_sec_item(buf, &offset, &append, "CCMP128");
516 }
517 if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_WEP104) {
518 _libwifi_add_sec_item(buf, &offset, &append, "WEP104");
519 }
520 if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_BIP_CMAC128) {
521 _libwifi_add_sec_item(buf, &offset, &append, "BIP_CMAC128");
522 }
523 if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_NOTALLOWED) {
524 _libwifi_add_sec_item(buf, &offset, &append, "NOT_ALLOWED");
525 }
526 if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_GCMP128) {
527 _libwifi_add_sec_item(buf, &offset, &append, "GCMP128");
528 }
529 if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_GCMP256) {
530 _libwifi_add_sec_item(buf, &offset, &append, "GCMP256");
531 }
532 if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_CCMP256) {
533 _libwifi_add_sec_item(buf, &offset, &append, "CCMP256");
534 }
535 if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_BIP_GMAC128) {
536 _libwifi_add_sec_item(buf, &offset, &append, "BIP_GMAC128");
537 }
538 if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_BIP_GMAC256) {
539 _libwifi_add_sec_item(buf, &offset, &append, "BIP_GMAC256");
540 }
541 if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_BIP_CMAC256) {
542 _libwifi_add_sec_item(buf, &offset, &append, "BIP_CMAC256");
543 }
544}
545
546void libwifi_get_pairwise_ciphers(struct libwifi_bss *bss, char *buf) {
547 memset(buf, 0, LIBWIFI_SECURITY_BUF_LEN);
548
549 int offset = 0;
550 int append = 0;
551
552 if (bss->encryption_info == 0) {
553 snprintf(buf + offset, LIBWIFI_SECURITY_BUF_LEN, "None");
554 return;
555 }
556
557 if (bss->encryption_info & LIBWIFI_PAIRWISE_SUITE_GROUP) {
558 _libwifi_add_sec_item(buf, &offset, &append, "GROUP");
559 }
560 if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_WEP40) {
561 _libwifi_add_sec_item(buf, &offset, &append, "WEP40");
562 }
563 if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_TKIP) {
564 _libwifi_add_sec_item(buf, &offset, &append, "TKIP");
565 }
566 if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_RESERVED) {
567 _libwifi_add_sec_item(buf, &offset, &append, "RESERVED");
568 }
569 if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_CCMP128) {
570 _libwifi_add_sec_item(buf, &offset, &append, "CCMP128");
571 }
572 if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_WEP104) {
573 _libwifi_add_sec_item(buf, &offset, &append, "WEP104");
574 }
575 if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_CMAC128) {
576 _libwifi_add_sec_item(buf, &offset, &append, "BIP_CMAC128");
577 }
578 if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_NOTALLOWED) {
579 _libwifi_add_sec_item(buf, &offset, &append, "NOT_ALLOWED");
580 }
581 if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_GCMP128) {
582 _libwifi_add_sec_item(buf, &offset, &append, "GCMP128");
583 }
584 if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_GCMP256) {
585 _libwifi_add_sec_item(buf, &offset, &append, "GCMP256");
586 }
587 if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_CCMP256) {
588 _libwifi_add_sec_item(buf, &offset, &append, "CCMP256");
589 }
590 if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_GMAC128) {
591 _libwifi_add_sec_item(buf, &offset, &append, "BIP_GMAC128");
592 }
593 if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_GMAC256) {
594 _libwifi_add_sec_item(buf, &offset, &append, "BIP_GMAC256");
595 }
596 if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_CMAC256) {
597 _libwifi_add_sec_item(buf, &offset, &append, "BIP_CMAC256");
598 }
599}
600
601void libwifi_get_auth_key_suites(struct libwifi_bss *bss, char *buf) {
602 memset(buf, 0, LIBWIFI_SECURITY_BUF_LEN);
603
604 int offset = 0;
605 int append = 0;
606
607 if (bss->encryption_info == 0) {
608 snprintf(buf + offset, LIBWIFI_SECURITY_BUF_LEN, "None");
609 return;
610 }
611
612 if (bss->encryption_info & LIBWIFI_AKM_SUITE_RESERVED) {
613 _libwifi_add_sec_item(buf, &offset, &append, "RESERVED");
614 }
615 if (bss->encryption_info & LIBWIFI_AKM_SUITE_1X) {
616 _libwifi_add_sec_item(buf, &offset, &append, "802.1X");
617 }
618 if (bss->encryption_info & LIBWIFI_AKM_SUITE_PSK) {
619 _libwifi_add_sec_item(buf, &offset, &append, "PSK");
620 }
621 if (bss->encryption_info & LIBWIFI_AKM_SUITE_1X_FT) {
622 _libwifi_add_sec_item(buf, &offset, &append, "802.1X_FT");
623 }
624 if (bss->encryption_info & LIBWIFI_AKM_SUITE_PSK_FT) {
625 _libwifi_add_sec_item(buf, &offset, &append, "PSK_FT");
626 }
627 if (bss->encryption_info & LIBWIFI_AKM_SUITE_1X_SHA256) {
628 _libwifi_add_sec_item(buf, &offset, &append, "802.1X_SHA256");
629 }
630 if (bss->encryption_info & LIBWIFI_AKM_SUITE_PSK_SHA256) {
631 _libwifi_add_sec_item(buf, &offset, &append, "PSK_SHA256");
632 }
633 if (bss->encryption_info & LIBWIFI_AKM_SUITE_TDLS) {
634 _libwifi_add_sec_item(buf, &offset, &append, "TDLS");
635 }
636 if (bss->encryption_info & LIBWIFI_AKM_SUITE_SAE) {
637 _libwifi_add_sec_item(buf, &offset, &append, "SAE");
638 }
639 if (bss->encryption_info & LIBWIFI_AKM_SUITE_SAE_FT) {
640 _libwifi_add_sec_item(buf, &offset, &append, "SAE_FT");
641 }
642 if (bss->encryption_info & LIBWIFI_AKM_SUITE_AP_PEER) {
643 _libwifi_add_sec_item(buf, &offset, &append, "AP_PEER");
644 }
645 if (bss->encryption_info & LIBWIFI_AKM_SUITE_1X_SUITEB_SHA256) {
646 _libwifi_add_sec_item(buf, &offset, &append, "802.1X_SUITEB_SHA256");
647 }
648 if (bss->encryption_info & LIBWIFI_AKM_SUITE_1X_SUITEB_SHA384) {
649 _libwifi_add_sec_item(buf, &offset, &append, "802.1X_SUITEB_SHA384");
650 }
651 if (bss->encryption_info & LIBWIFI_AKM_SUITE_1X_FT_SHA384) {
652 _libwifi_add_sec_item(buf, &offset, &append, "802.1X_FT_SHA384");
653 }
654 if (bss->encryption_info & LIBWIFI_AKM_SUITE_FILS_SHA256) {
655 _libwifi_add_sec_item(buf, &offset, &append, "FILS_SHA256");
656 }
657 if (bss->encryption_info & LIBWIFI_AKM_SUITE_FILS_SHA384) {
658 _libwifi_add_sec_item(buf, &offset, &append, "FILS_SHA384");
659 }
660 if (bss->encryption_info & LIBWIFI_AKM_SUITE_FILS_SHA256_FT) {
661 _libwifi_add_sec_item(buf, &offset, &append, "FILS_SHA256_FT");
662 }
663 if (bss->encryption_info & LIBWIFI_AKM_SUITE_FILS_SHA384_FT) {
664 _libwifi_add_sec_item(buf, &offset, &append, "FILS_SHA384_FT");
665 }
666 if (bss->encryption_info & LIBWIFI_AKM_SUITE_OWE) {
667 _libwifi_add_sec_item(buf, &offset, &append, "OWE");
668 }
669 if (bss->encryption_info & LIBWIFI_AKM_PSK_SHA384_FT) {
670 _libwifi_add_sec_item(buf, &offset, &append, "PSK_SHA384_FT");
671 }
672 if (bss->encryption_info & LIBWIFI_AKM_PSK_SHA384) {
673 _libwifi_add_sec_item(buf, &offset, &append, "PSK_SHA384");
674 }
675}
676
677void _libwifi_add_sec_item(char *buf, int *offset, int *append, char *item) {
678 if (*append) {
679 snprintf(buf + *offset, LIBWIFI_SECURITY_BUF_LEN, ", ");
680 *offset += strlen(", ");
681 }
682 snprintf(buf + *offset, LIBWIFI_SECURITY_BUF_LEN, "%s", item);
683 *offset += strlen(item);
684 *append = 1;
685}
diff --git a/src/libwifi/parse/misc/security.h b/src/libwifi/parse/misc/security.h new file mode 100644 index 0000000..dba2850 --- /dev/null +++ b/src/libwifi/parse/misc/security.h
@@ -0,0 +1,124 @@
1/* Copyright 2021 The libwifi Authors
2 *
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#ifndef LIBWIFI_PARSE_SECURITY_H
17#define LIBWIFI_PARSE_SECURITY_H
18
19#include "../../core/frame/management/common.h"
20#include "../../core/misc/security.h"
21
22#include <stdint.h>
23
24#define LIBWIFI_SECURITY_BUF_LEN 256
25
26/**
27 * Get the RSN related information and store it in a
28 * libwifi_rsn_info. This function will detect and enumerate
29 * cipher suites, and AKM suites, and the RSN capabilities
30 * from a specified RSN IE.
31 *
32 * @param info A libwifi_rsn_info
33 * @param tag_data An RSN IE tag
34 * @param tag_end The end of the specified RSN IE tag
35 * @return
36 */
37int libwifi_get_rsn_info(struct libwifi_rsn_info *info, const unsigned char *tag_data,
38 const unsigned char *tag_end);
39
40/**
41 * Enumerate the RSN cipher suites in a libwifi_rsn_info.
42 *
43 * This function can be used to fill a libwifi_bss struct
44 * with information related to the cipher suites and AKM suites
45 * in the specified libwifi_rsn_info.
46 *
47 * @param rsn_info A libwifi_rsn_info
48 * @param libwifi_bss A libwifi_bss
49 */
50void libwifi_enumerate_rsn_suites(struct libwifi_rsn_info *rsn_info, struct libwifi_bss *bss);
51
52/**
53 * Get the WPA related information and store it in a
54 * libwifi_wpa_info. This function will detect and enumerate
55 * cipher suites and AKM suites from a specified WPA IE.
56 *
57 * @param info A libwifi_wpa_info
58 * @param tag_data A WPA IE tag
59 * @param tag_end The end of the specified WPA IE tag
60 * @return
61 */
62int libwifi_get_wpa_info(struct libwifi_wpa_info *info, const unsigned char *tag_data,
63 const unsigned char *tag_end);
64
65/**
66 * Enumerate the WPA cipher suites in a libwifi_wpa_info.
67 *
68 * This function can be used to fill a libwifi_bss struct
69 * with information related to the cipher suites and AKM suites
70 * in the specified libwifi_wpa_info.
71 *
72 * @param wpa_info A libwifi_wpa_info
73 * @param libwifi_bss A libwifi_bss
74 */
75void libwifi_enumerate_wpa_suites(struct libwifi_wpa_info *wpa_info, struct libwifi_bss *bss);
76
77/**
78 * Enumerate the security types (WEP, WPA, WPA2, WPA3, etc) in a given libwifi_bss,
79 * formatted into the given buffer.
80 *
81 * @param bss A libwifi_bss struct
82 * @param buf A buffer of length LIBWIFI_SECURITY_BUF_LEN
83 */
84void libwifi_get_security_type(struct libwifi_bss *bss, char *buf);
85
86/**
87 * Enumerate the group ciphers (CCMP, GCMP128, etc) in a given libwifi_bss,
88 * formatted into the given buffer.
89 *
90 * @param bss A libwifi_bss struct
91 * @param buf A buffer of length LIBWIFI_SECURITY_BUF_LEN
92 */
93void libwifi_get_group_ciphers(struct libwifi_bss *bss, char *buf);
94
95/**
96 * Enumerate the pairwise ciphers (GROUP, CCMP, BIP_CMAC128, etc) in a given libwifi_bss,
97 * formatted into the given buffer.
98 *
99 * @param bss A libwifi_bss struct
100 * @param buf A buffer of length LIBWIFI_SECURITY_BUF_LEN
101 */
102void libwifi_get_pairwise_ciphers(struct libwifi_bss *bss, char *buf);
103
104/**
105 * Enumerate the auth key management suites in a given libwifi_bss,
106 * formatted into the given buffer.
107 *
108 * @param bss A libwifi_bss struct
109 * @param buf A buffer of length LIBWIFI_SECURITY_BUF_LEN
110 */
111void libwifi_get_auth_key_suites(struct libwifi_bss *bss, char *buf);
112
113/**
114 * Internal function for adding a formatted string to a buffer for use with
115 * libwifi_get_* security functions.
116 *
117 * @param buf A buffer of length LIBWIFI_SECURITY_BUF_LEN
118 * @param offset A pointer to the current buffer offset variable
119 * @param append A pointer to the append state variable
120 * @param item A pointer to the string to append to the given buf
121 */
122void _libwifi_add_sec_item(char *buf, int *offset, int *append, char *item);
123
124#endif /* LIBWIFI_PARSE_SECURITY_H */
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100644 index 0000000..b418f93 --- /dev/null +++ b/test/CMakeLists.txt
@@ -0,0 +1,16 @@
1cmake_minimum_required(VERSION 3.18)
2
3project(libwifi_tests VERSION 0.1)
4
5set(CMAKE_CXX_STANDARD 11)
6set(CMAKE_CXX_STANDARD_REQUIRED True)
7
8set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ggdb -O0")
9
10add_executable(test_misc src/helpers.c src/test_misc.c)
11add_executable(test_generation src/helpers.c src/test_generation.c)
12add_executable(test_parsing src/helpers.c src/test_parsing.c)
13
14target_link_libraries(test_misc wifi)
15target_link_libraries(test_generation wifi pcap)
16target_link_libraries(test_parsing wifi pcap)
diff --git a/test/pcaps/assoc_req.pcap b/test/pcaps/assoc_req.pcap new file mode 100644 index 0000000..87ad19b --- /dev/null +++ b/test/pcaps/assoc_req.pcap
Binary files differ
diff --git a/test/pcaps/assoc_resp.pcap b/test/pcaps/assoc_resp.pcap new file mode 100644 index 0000000..16f6fad --- /dev/null +++ b/test/pcaps/assoc_resp.pcap
Binary files differ
diff --git a/test/pcaps/auth.pcap b/test/pcaps/auth.pcap new file mode 100644 index 0000000..e667432 --- /dev/null +++ b/test/pcaps/auth.pcap
Binary files differ
diff --git a/test/pcaps/beacons_with_221.pcap b/test/pcaps/beacons_with_221.pcap new file mode 100644 index 0000000..5cc20ff --- /dev/null +++ b/test/pcaps/beacons_with_221.pcap
Binary files differ
diff --git a/test/pcaps/deauth.pcap b/test/pcaps/deauth.pcap new file mode 100644 index 0000000..c8fb77c --- /dev/null +++ b/test/pcaps/deauth.pcap
Binary files differ
diff --git a/test/pcaps/deauth_with_221.pcap b/test/pcaps/deauth_with_221.pcap new file mode 100644 index 0000000..ba53dd1 --- /dev/null +++ b/test/pcaps/deauth_with_221.pcap
Binary files differ
diff --git a/test/pcaps/disassoc.pcap b/test/pcaps/disassoc.pcap new file mode 100644 index 0000000..f217150 --- /dev/null +++ b/test/pcaps/disassoc.pcap
Binary files differ
diff --git a/test/pcaps/probe_req.pcap b/test/pcaps/probe_req.pcap new file mode 100644 index 0000000..b039e4b --- /dev/null +++ b/test/pcaps/probe_req.pcap
Binary files differ
diff --git a/test/pcaps/probe_resp_with_221.pcap b/test/pcaps/probe_resp_with_221.pcap new file mode 100644 index 0000000..3d664b0 --- /dev/null +++ b/test/pcaps/probe_resp_with_221.pcap
Binary files differ
diff --git a/test/pcaps/reassoc_req.pcap b/test/pcaps/reassoc_req.pcap new file mode 100644 index 0000000..f5bd99e --- /dev/null +++ b/test/pcaps/reassoc_req.pcap
Binary files differ
diff --git a/test/pcaps/reassoc_resp.pcap b/test/pcaps/reassoc_resp.pcap new file mode 100644 index 0000000..c3e657f --- /dev/null +++ b/test/pcaps/reassoc_resp.pcap
Binary files differ
diff --git a/test/src/.clang-format b/test/src/.clang-format new file mode 100644 index 0000000..111249f --- /dev/null +++ b/test/src/.clang-format
@@ -0,0 +1,8 @@
1---
2BasedOnStyle: LLVM
3IndentWidth: '4'
4SpaceAfterCStyleCast: 'true'
5ColumnLimit: 400
6AllowShortFunctionsOnASingleLine: None
7IndentCaseLabels: 'true'
8...
diff --git a/test/src/helpers.c b/test/src/helpers.c new file mode 100644 index 0000000..9fc9d0b --- /dev/null +++ b/test/src/helpers.c
@@ -0,0 +1,31 @@
1#include "helpers.h"
2#include <stdio.h>
3
4void hexdump(void *data, size_t size) {
5 char ascii[17];
6 size_t i, j;
7 ascii[16] = '\0';
8 for (i = 0; i < size; ++i) {
9 printf("%02X ", ((unsigned char *) data)[i]);
10 if (((unsigned char *) data)[i] >= ' ' && ((unsigned char *) data)[i] <= '~') {
11 ascii[i % 16] = ((unsigned char *) data)[i];
12 } else {
13 ascii[i % 16] = '.';
14 }
15 if ((i + 1) % 8 == 0 || i + 1 == size) {
16 printf(" ");
17 if ((i + 1) % 16 == 0) {
18 printf("| %s \n", ascii);
19 } else if (i + 1 == size) {
20 ascii[(i + 1) % 16] = '\0';
21 if ((i + 1) % 16 <= 8) {
22 printf(" ");
23 }
24 for (j = (i + 1) % 16; j < 16; ++j) {
25 printf(" ");
26 }
27 printf("| %s \n", ascii);
28 }
29 }
30 }
31}
diff --git a/test/src/helpers.h b/test/src/helpers.h new file mode 100644 index 0000000..99a5329 --- /dev/null +++ b/test/src/helpers.h
@@ -0,0 +1,60 @@
1#include <stdint.h>
2#include <sys/types.h>
3
4#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
5#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
6
7static const uint8_t radiotap_data[] = {
8 0x00,
9 0x00, // <-- radiotap version (ignore this)
10 0x18,
11 0x00, // <-- number of bytes in our header (count the number of "0x"s)
12
13 /**
14 * The next field is a bitmap of which options we are including.
15 * The full list of which field is which option is in ieee80211_radiotap.h,
16 * but I've chosen to include:
17 * 0x00 0x01: timestamp
18 * 0x00 0x02: flags
19 * 0x00 0x03: rate
20 * 0x00 0x04: channel
21 * 0x80 0x00: tx flags (seems silly to have this AND flags, but oh well)
22 */
23 0x0f,
24 0x80,
25 0x00,
26 0x00,
27
28 0x00,
29 0x00,
30 0x00,
31 0x00,
32 0x00,
33 0x00,
34 0x00,
35 0x00, // <-- timestamp
36
37 /**
38 * This is the first set of flags, and we've set the bit corresponding to
39 * IEEE80211_RADIOTAP_F_FCS, meaning we want the card to add a FCS at the
40 * end of our buffer for us.
41 */
42 0x10,
43
44 0x00, // <-- rate
45 0x00,
46 0x00,
47 0x00,
48 0x00, // <-- channel
49
50 /**
51 * This is the second set of flags, specifically related to transmissions.
52 * The bit we've set is IEEE80211_RADIOTAP_F_TX_NOACK, which means the card
53 * won't wait for an ACK for this frame, and that it won't retry if it
54 * doesn't get one.
55 */
56 0x08,
57 0x00,
58};
59
60void hexdump(void *data, size_t size);
diff --git a/test/src/test_generation.c b/test/src/test_generation.c new file mode 100644 index 0000000..407e87f --- /dev/null +++ b/test/src/test_generation.c
@@ -0,0 +1,924 @@
1#include <errno.h>
2#include <libwifi.h>
3#include <libwifi/core/frame/management/action.h>
4#include <libwifi/core/frame/management/timing_ad.h>
5#include <libwifi/core/frame/tag.h>
6#include <libwifi/core/misc/types.h>
7#include <libwifi/gen/management/timing_ad.h>
8#include <pcap.h>
9#include <pcap/dlt.h>
10#include <pcap/pcap.h>
11#include <signal.h>
12#include <stddef.h>
13#include <stdint.h>
14#include <stdio.h>
15#include <stdlib.h>
16#include <string.h>
17#include <sys/time.h>
18#include <unistd.h>
19
20#include "helpers.h"
21
22#define LIVE_INJECT 0
23#define OFFLINE_DUMP 1
24
25#define MODE_BEACON 0
26#define MODE_PROBE_RESPONSE 1
27#define MODE_PROBE_REQUEST 2
28#define MODE_DEAUTH 3
29#define MODE_DISASSOC 4
30#define MODE_ASSOC_RESPONSE 5
31#define MODE_ASSOC_REQUEST 6
32#define MODE_REASSOC_RESPONSE 7
33#define MODE_REASSOC_REQUEST 8
34#define MODE_AUTH 9
35#define MODE_RTS 10
36#define MODE_CTS 11
37#define MODE_RANDOM_BEACON 12
38#define MODE_ACTION 13
39#define MODE_ACTION_NOACK 14
40#define MODE_TIMING_AD 15
41#define MODE_ATIM 16
42
43#define SNAPLEN 96
44#define CHANNEL 11
45#define BCAST_MAC "\xff\xff\xff\xff\xff\xff"
46#define TO_MAC "\x00\x20\x91\xAA\xBB\xCC"
47#define FROM_MAC "\x00\x20\x91\x11\x22\x33"
48#define REASSOC_MAC "\xAA\xBB\xCC\xDD\xEE\xFF"
49#define BEACON_SSID "libwifi-beacon"
50#define PROBE_RESP_SSID "libwifi-probe-resp"
51#define PROBE_REQ_SSID "libwifi-probe-req"
52#define ASSOC_REQ_SSID "libwifi-assoc-req"
53#define REASSOC_REQ_SSID "libwifi-reassoc-req"
54
55pcap_t *handle = NULL;
56pcap_dumper_t *outputHandle = NULL;
57FILE *filename = NULL;
58
59static unsigned char to[] = TO_MAC;
60static unsigned char from[] = FROM_MAC;
61static unsigned char bcast[] = BCAST_MAC;
62static unsigned char reassoc_mac[] = REASSOC_MAC;
63static unsigned char tag_data[] = "\x00\x00\00\x01This is a 221 tag from libwifi.\n";
64
65static int mode = 0;
66static int inject_mode = 0;
67
68void handle_interupt(int signal) {
69 if (signal == SIGINT) {
70 int oldmode = inject_mode;
71 mode = -1;
72 inject_mode = -1;
73
74 if (oldmode == LIVE_INJECT) {
75 pcap_close(handle);
76 printf("\n\nClosed Capture Handle!\n");
77 } else if (oldmode == OFFLINE_DUMP) {
78 pcap_dump_flush(outputHandle);
79 pcap_dump_close(outputHandle);
80 printf("\n\nDumped and Closed Output File!\n");
81 }
82
83 exit(EXIT_SUCCESS);
84 }
85}
86
87void inject_frame(void *buf, size_t buf_sz) {
88 struct libwifi_radiotap_info info = {0};
89 info.present = 0x0000002e; // 0x002e: Flags, Rate, Channel, dBm Ant Signal
90 info.channel.flags = 0x0140; // OFDM, 5GHz
91 info.channel.freq = 5180; // Channel 46
92 info.flags = 0x0000; // No Flags
93 info.rate = 1; // 1 Mbit
94 info.rate_raw = info.rate * 2; // Radiotap uses 500kb/s increments
95 info.signal = -20; // Signal in dBm
96
97 char *rtap = NULL;
98 rtap = malloc(LIBWIFI_MAX_RADIOTAP_LEN);
99 if (rtap == NULL) {
100 printf("malloc failure: %s\n", strerror(errno));
101 return;
102 }
103 memset(rtap, 0, LIBWIFI_MAX_RADIOTAP_LEN);
104
105 int rtap_len = libwifi_create_radiotap(&info, rtap);
106 if (rtap_len == -1) {
107 printf("error generating radiotap header\n");
108 return;
109 }
110
111 void *frame = NULL;
112 size_t frame_sz = rtap_len + buf_sz;
113 frame = malloc(frame_sz);
114 if (frame == NULL) {
115 printf("malloc failure: %s\n", strerror(errno));
116 exit(EXIT_FAILURE);
117 }
118
119 memcpy(frame, rtap, rtap_len);
120 memcpy(frame + rtap_len, buf, buf_sz);
121
122 hexdump(rtap, rtap_len);
123 printf("-----\n");
124 hexdump(frame, frame_sz);
125
126 if (inject_mode == LIVE_INJECT) {
127 pcap_inject(handle, frame, frame_sz);
128 } else if (inject_mode == OFFLINE_DUMP) {
129 struct pcap_pkthdr hdr = {0};
130 hdr.caplen = frame_sz;
131 hdr.len = frame_sz;
132 struct timeval tv;
133 gettimeofday(&tv, NULL);
134 hdr.ts = tv;
135 pcap_dump((unsigned char *) outputHandle, &hdr, frame);
136 }
137
138 free(rtap);
139 free(frame);
140}
141
142void inject_beacons(int random_mac) {
143 while (1) {
144 printf("Sending 50 beacons...\n");
145 for (int i = 0; i < 50; ++i) {
146 struct libwifi_beacon beacon;
147 unsigned char txmac[6] = {0};
148 memset(&beacon, 0, sizeof(struct libwifi_beacon));
149
150 if (random_mac) {
151 libwifi_random_mac(txmac, NULL);
152 } else {
153 memcpy(txmac, FROM_MAC, 6);
154 }
155 libwifi_create_beacon(&beacon, bcast, txmac, BEACON_SSID, CHANNEL);
156 libwifi_quick_add_tag(&beacon.tags, TAG_VENDOR_SPECIFIC, tag_data, sizeof(tag_data));
157
158 unsigned char *buf = NULL;
159 size_t buf_sz = libwifi_get_beacon_length(&beacon);
160
161 buf = malloc(buf_sz);
162 if (buf == NULL) {
163 printf("malloc failure: %s", strerror(errno));
164 exit(EXIT_FAILURE);
165 }
166
167 printf("Injecting beacon with:\n");
168 printf("\tSSID: %s\n", BEACON_SSID);
169 printf("\tChannel: %d\n", CHANNEL);
170 printf("\tSource: " MACSTR "\n", MAC2STR(txmac));
171 printf("\tDestination: " MACSTR "\n", MAC2STR(bcast));
172
173 libwifi_dump_beacon(&beacon, buf, buf_sz);
174 inject_frame(buf, buf_sz);
175
176 libwifi_free_beacon(&beacon);
177 free(buf);
178 usleep(1e4); // 10ms
179 }
180 sleep(1);
181 }
182}
183
184void inject_probe_responses() {
185 while (1) {
186 printf("Sending 50 probe responses, then sleeping for 1 second\n");
187 for (int i = 0; i < 50; ++i) {
188 struct libwifi_probe_resp probe_resp;
189 memset(&probe_resp, 0, sizeof(struct libwifi_probe_resp));
190
191 libwifi_create_probe_resp(&probe_resp, to, from, PROBE_RESP_SSID, CHANNEL);
192 libwifi_quick_add_tag(&probe_resp.tags, TAG_VENDOR_SPECIFIC, tag_data, sizeof(tag_data));
193
194 unsigned char *buf = NULL;
195 size_t buf_sz = libwifi_get_probe_resp_length(&probe_resp);
196
197 buf = malloc(buf_sz);
198 if (buf == NULL) {
199 printf("malloc failure: %s", strerror(errno));
200 exit(EXIT_FAILURE);
201 }
202
203 printf("Injecting probe responses with:\n");
204 printf("\tSSID: %s\n", PROBE_RESP_SSID);
205 printf("\tChannel: %d\n", CHANNEL);
206 printf("\tSource: " MACSTR "\n", MAC2STR(from));
207 printf("\tDestination: " MACSTR "\n", MAC2STR(to));
208
209 libwifi_dump_probe_resp(&probe_resp, buf, buf_sz);
210 inject_frame(buf, buf_sz);
211
212 libwifi_free_probe_resp(&probe_resp);
213 free(buf);
214 usleep(1e4); // 10ms
215 }
216 sleep(1);
217 }
218}
219
220void inject_probe_requests() {
221 while (1) {
222 printf("Sending 50 probe responses, then sleeping for 1 second\n");
223 for (int i = 0; i < 50; ++i) {
224 struct libwifi_probe_req probe;
225 memset(&probe, 0, sizeof(struct libwifi_probe_req));
226
227 libwifi_create_probe_req(&probe, to, from, to, PROBE_REQ_SSID, CHANNEL);
228
229 unsigned char *buf = NULL;
230 size_t buf_sz = libwifi_get_probe_req_length(&probe);
231
232 buf = malloc(buf_sz);
233 if (buf == NULL) {
234 printf("malloc failure: %s", strerror(errno));
235 exit(EXIT_FAILURE);
236 }
237
238 printf("Injecting probe requests with:\n");
239 printf("\tSSID: %s\n", PROBE_REQ_SSID);
240 printf("\tChannel: %d\n", CHANNEL);
241 printf("\tSource: " MACSTR "\n", MAC2STR(from));
242 printf("\tDestination: " MACSTR "\n", MAC2STR(to));
243
244 libwifi_dump_probe_req(&probe, buf, buf_sz);
245 inject_frame(buf, buf_sz);
246
247 libwifi_free_probe_req(&probe);
248 free(buf);
249
250 usleep(1e4); // 10ms
251 }
252 sleep(1);
253 }
254}
255
256void inject_deauths() {
257 while (1) {
258 printf("Sending 50 probe responses, then sleeping for 1 second\n");
259 for (int i = 0; i < 50; ++i) {
260 struct libwifi_deauth deauth;
261 memset(&deauth, 0, sizeof(struct libwifi_deauth));
262
263 libwifi_create_deauth(&deauth, to, from, REASON_STA_LEAVING);
264
265 unsigned char *buf = NULL;
266 size_t buf_sz = libwifi_get_deauth_length(&deauth);
267
268 buf = malloc(buf_sz);
269 if (buf == NULL) {
270 printf("malloc failure: %s", strerror(errno));
271 exit(EXIT_FAILURE);
272 }
273
274 printf("Injecting deauths with:\n");
275 printf("\tChannel: %d\n", CHANNEL);
276 printf("\tReason: %d\n", REASON_STA_LEAVING);
277 printf("\tSource: " MACSTR "\n", MAC2STR(from));
278 printf("\tDestination: " MACSTR "\n", MAC2STR(to));
279
280 libwifi_dump_deauth(&deauth, buf, buf_sz);
281 inject_frame(buf, buf_sz);
282
283 free(buf);
284
285 usleep(1e4); // 10ms
286 }
287 sleep(1);
288 }
289}
290
291void inject_disassocs() {
292 while (1) {
293 printf("Sending 50 probe responses, then sleeping for 1 second\n");
294 for (int i = 0; i < 50; ++i) {
295 struct libwifi_disassoc disassoc;
296 memset(&disassoc, 0, sizeof(struct libwifi_disassoc));
297
298 libwifi_create_disassoc(&disassoc, to, from, REASON_STA_LEAVING);
299
300 unsigned char *buf = NULL;
301 size_t buf_sz = libwifi_get_disassoc_length(&disassoc);
302
303 buf = malloc(buf_sz);
304 if (buf == NULL) {
305 printf("malloc failure: %s", strerror(errno));
306 exit(EXIT_FAILURE);
307 }
308
309 printf("Injecting disassocs with:\n");
310 printf("\tChannel: %d\n", CHANNEL);
311 printf("\tReason: %d\n", REASON_STA_LEAVING);
312 printf("\tSource: " MACSTR "\n", MAC2STR(from));
313 printf("\tDestination: " MACSTR "\n", MAC2STR(to));
314
315 libwifi_dump_disassoc(&disassoc, buf, buf_sz);
316 inject_frame(buf, buf_sz);
317
318 free(buf);
319
320 usleep(1e4); // 10ms
321 }
322 sleep(1);
323 }
324}
325
326void inject_assoc_requests() {
327 while (1) {
328 printf("Sending 50 association requests, then sleeping for 1 second\n");
329 for (int i = 0; i < 50; ++i) {
330 struct libwifi_assoc_req assoc_req;
331 memset(&assoc_req, 0, sizeof(struct libwifi_assoc_req));
332
333 libwifi_create_assoc_req(&assoc_req, to, from, ASSOC_REQ_SSID, CHANNEL);
334
335 unsigned char *buf = NULL;
336 size_t buf_sz = libwifi_get_assoc_req_length(&assoc_req);
337
338 buf = malloc(buf_sz);
339 if (buf == NULL) {
340 printf("malloc failure: %s", strerror(errno));
341 exit(EXIT_FAILURE);
342 }
343
344 printf("Injecting association requests with:\n");
345 printf("\tChannel: %d\n", CHANNEL);
346 printf("\tSource: " MACSTR "\n", MAC2STR(from));
347 printf("\tDestination: " MACSTR "\n", MAC2STR(to));
348
349 libwifi_dump_assoc_req(&assoc_req, buf, buf_sz);
350 inject_frame(buf, buf_sz);
351
352 free(buf);
353 libwifi_free_assoc_req(&assoc_req);
354
355 usleep(1e4); // 10ms
356 }
357 sleep(1);
358 }
359}
360
361void inject_assoc_responses() {
362 while (1) {
363 printf("Sending 50 association responses, then sleeping for 1 second\n");
364 for (int i = 0; i < 50; ++i) {
365 struct libwifi_assoc_resp assoc_resp;
366 memset(&assoc_resp, 0, sizeof(struct libwifi_assoc_req));
367
368 libwifi_create_assoc_resp(&assoc_resp, to, from, CHANNEL);
369
370 unsigned char *buf = NULL;
371 size_t buf_sz = libwifi_get_assoc_resp_length(&assoc_resp);
372
373 buf = malloc(buf_sz);
374 if (buf == NULL) {
375 printf("malloc failure: %s", strerror(errno));
376 exit(EXIT_FAILURE);
377 }
378
379 printf("Injecting association responses with:\n");
380 printf("\tChannel: %d\n", CHANNEL);
381 printf("\tSource: " MACSTR "\n", MAC2STR(from));
382 printf("\tDestination: " MACSTR "\n", MAC2STR(to));
383
384 libwifi_dump_assoc_resp(&assoc_resp, buf, buf_sz);
385 inject_frame(buf, buf_sz);
386
387 free(buf);
388 libwifi_free_assoc_resp(&assoc_resp);
389
390 usleep(1e4); // 10ms
391 }
392 sleep(1);
393 }
394}
395
396void inject_reassoc_requests() {
397 while (1) {
398 printf("Sending 50 reassociation requests, then sleeping for 1 second\n");
399 for (int i = 0; i < 50; ++i) {
400 struct libwifi_reassoc_req reassoc_req;
401 memset(&reassoc_req, 0, sizeof(struct libwifi_assoc_req));
402
403 libwifi_create_reassoc_req(&reassoc_req, to, from, reassoc_mac, REASSOC_REQ_SSID, CHANNEL);
404
405 unsigned char *buf = NULL;
406 size_t buf_sz = libwifi_get_reassoc_req_length(&reassoc_req);
407
408 buf = malloc(buf_sz);
409 if (buf == NULL) {
410 printf("malloc failure: %s", strerror(errno));
411 exit(EXIT_FAILURE);
412 }
413
414 printf("Injecting reassociation requests with:\n");
415 printf("\tChannel: %d\n", CHANNEL);
416 printf("\tSource: " MACSTR "\n", MAC2STR(from));
417 printf("\tDestination: " MACSTR "\n", MAC2STR(to));
418 printf("\tPrevious BSSID: " MACSTR "\n", MAC2STR(reassoc_mac));
419
420 libwifi_dump_reassoc_req(&reassoc_req, buf, buf_sz);
421 inject_frame(buf, buf_sz);
422
423 free(buf);
424 libwifi_free_reassoc_req(&reassoc_req);
425
426 usleep(1e4); // 10ms
427 }
428 sleep(1);
429 }
430}
431
432void inject_reassoc_responses() {
433 while (1) {
434 printf("Sending 50 reassociation responses, then sleeping for 1 second\n");
435 for (int i = 0; i < 50; ++i) {
436 struct libwifi_reassoc_resp reassoc_resp;
437 memset(&reassoc_resp, 0, sizeof(struct libwifi_assoc_req));
438
439 libwifi_create_reassoc_resp(&reassoc_resp, to, from, CHANNEL);
440
441 unsigned char *buf = NULL;
442 size_t buf_sz = libwifi_get_reassoc_resp_length(&reassoc_resp);
443
444 buf = malloc(buf_sz);
445 if (buf == NULL) {
446 printf("malloc failure: %s", strerror(errno));
447 exit(EXIT_FAILURE);
448 }
449
450 printf("Injecting reassociation responses with:\n");
451 printf("\tChannel: %d\n", CHANNEL);
452 printf("\tSource: " MACSTR "\n", MAC2STR(from));
453 printf("\tDestination: " MACSTR "\n", MAC2STR(to));
454
455 libwifi_dump_reassoc_resp(&reassoc_resp, buf, buf_sz);
456 inject_frame(buf, buf_sz);
457
458 free(buf);
459 libwifi_free_reassoc_resp(&reassoc_resp);
460
461 usleep(1e4); // 10ms
462 }
463 sleep(1);
464 }
465}
466
467void inject_auths() {
468 while (1) {
469 printf("Sending 50 auth frames, then sleeping for 1 second\n");
470 for (int i = 0; i < 50; ++i) {
471 struct libwifi_auth auth;
472 memset(&auth, 0, sizeof(struct libwifi_deauth));
473
474 libwifi_create_auth(&auth, to, from, AUTH_OPEN, 0, STATUS_SUCCESS);
475
476 unsigned char *buf = NULL;
477 size_t buf_sz = libwifi_get_auth_length(&auth);
478
479 buf = malloc(buf_sz);
480 if (buf == NULL) {
481 printf("malloc failure: %s", strerror(errno));
482 exit(EXIT_FAILURE);
483 }
484
485 libwifi_dump_auth(&auth, buf, buf_sz);
486 inject_frame(buf, buf_sz);
487
488 free(buf);
489
490 memset(&auth, 0, sizeof(struct libwifi_deauth));
491
492 libwifi_create_auth(&auth, from, to, AUTH_OPEN, 1, STATUS_SUCCESS);
493
494 buf = NULL;
495 buf_sz = libwifi_get_auth_length(&auth);
496
497 buf = malloc(buf_sz);
498 if (buf == NULL) {
499 printf("malloc failure: %s", strerror(errno));
500 exit(EXIT_FAILURE);
501 }
502
503 printf("Injecting auths with:\n");
504 printf("\tChannel: %d\n", CHANNEL);
505 printf("\tAlgorithm: %d\n", AUTH_OPEN);
506 printf("\tSource: " MACSTR "\n", MAC2STR(from));
507 printf("\tDestination: " MACSTR "\n", MAC2STR(to));
508
509 libwifi_dump_auth(&auth, buf, buf_sz);
510 inject_frame(buf, buf_sz);
511
512 free(buf);
513 usleep(1e4); // 10ms
514 }
515 sleep(1);
516 }
517}
518
519void inject_timing_ads() {
520 while (1) {
521 printf("Sending 50 timing advertisement frames, then sleeping for 1 second\n");
522 for (int i = 0; i < 50; ++i) {
523 struct libwifi_timing_advert time_ad = {0};
524 struct libwifi_timing_advert_fields ad_fields = {0};
525
526 ad_fields.timing_capabilities = 2;
527 memcpy(ad_fields.time_error, "\xCC\xCC\xCC\xCC\xCC", 5);
528 memcpy(ad_fields.time_update, "\xBB", 1);
529 memcpy(ad_fields.time_value,
530 "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA", 10);
531
532 libwifi_create_timing_advert(&time_ad, to, from, &ad_fields, "GB", -56, -56, -30, -20);
533
534 unsigned char *buf = NULL;
535 size_t buf_len = libwifi_get_timing_advert_length(&time_ad);
536 buf = malloc(buf_len);
537 if (buf == NULL) {
538 printf("malloc failure: %s", strerror(errno));
539 exit(EXIT_FAILURE);
540 }
541 printf("buf_len: %zu\n", buf_len);
542
543 size_t ret = libwifi_dump_timing_advert(&time_ad, buf, buf_len);
544 if (ret < 0) {
545 printf("error dump: %zu\n", ret);
546 exit(EXIT_FAILURE);
547 }
548 hexdump(buf, buf_len);
549 inject_frame(buf, buf_len);
550
551 free(buf);
552 libwifi_free_timing_advert(&time_ad);
553
554 usleep(1e4); // 10ms
555 }
556 sleep(1);
557 }
558}
559
560void inject_action_noacks() {
561 while (1) {
562 printf("Sending 50 action no ack frames, then sleeping for 1 second\n");
563 for (int i = 0; i < 50; ++i) {
564 struct libwifi_action action;
565 memset(&action, 0, sizeof(struct libwifi_action));
566
567 libwifi_create_action_no_ack(&action, to, from, ACTION_FAST_BSS_TRANSITION);
568
569 unsigned char *action_buf = malloc(256);
570 memset(action_buf, 0, 256);
571
572 size_t offset = 0;
573 size_t w = 0;
574
575 memcpy(action_buf, "\x01", 1); // Fast BSS Request
576 offset += 1;
577 memcpy(action_buf + offset, "\xAA\xBB\xCC\xDD\xEE\xFF", 6); // STA Address
578 offset += 6;
579 memcpy(action_buf + offset, "\xFF\xEE\xDD\xCC\xBB\xAA", 6); // AP Address
580 offset += 6;
581
582 unsigned char *tag_tmp = malloc(256);
583 memset(tag_tmp, 0, 256);
584
585 struct libwifi_tagged_parameter rsne = {0};
586 size_t tsz = libwifi_create_tag(&rsne, TAG_RSN, (const unsigned char * )"\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x02\x00\x00", 20);
587 w = libwifi_dump_tag(&rsne, tag_tmp, tsz);
588 memcpy(action_buf + offset, tag_tmp, w);
589 offset += w;
590
591
592 struct libwifi_tagged_parameter mobdom = {0};
593 tsz = libwifi_create_tag(&mobdom, TAG_MOBILITY_DOMAIN, (const unsigned char*)"\x00\x11\x01", 3);
594 memset(tag_tmp, 0, tsz);
595 w = libwifi_dump_tag(&mobdom, tag_tmp, tsz);
596 memcpy(action_buf + offset, tag_tmp, w);
597 offset += w;
598 libwifi_free_tag(&mobdom);
599
600 struct libwifi_tagged_parameter fbss = {0};
601 tsz = libwifi_create_tag(&fbss, TAG_FAST_BSS_TRANSITION, (const unsigned char*)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xAA\xBB\xCC\xDD\xEE\xFF\xAA\xBB\xCC\xDD\xEE\xFF\xAA\xBB\xCC\xDD\xEE\xFF\xAA\xBB\xCC\xDD\xEE\xFF\xAA\xBB\xCC\xDD\xEE\xFF\xAA\x03\x04\xAA\xBB\x04\xAA\xBB\xCC\xDD", 88);
602 memset(tag_tmp, 0, tsz);
603 w = libwifi_dump_tag(&fbss, tag_tmp, tsz);
604 memcpy(action_buf + offset, tag_tmp, w);
605 offset += w;
606 libwifi_free_tag(&fbss);
607
608 libwifi_add_action_detail(&action.fixed_parameters.details, action_buf, offset);
609
610 unsigned char *buf = NULL;
611 size_t buf_sz = libwifi_get_action_length(&action);
612
613 buf = malloc(buf_sz);
614 if (buf == NULL) {
615 printf("malloc failure: %s", strerror(errno));
616 exit(EXIT_FAILURE);
617 }
618
619 printf("Injecting actions with:\n");
620 printf("\tAction: %d\n", ACTION_FAST_BSS_TRANSITION);
621 printf("\tSource: " MACSTR "\n", MAC2STR(from));
622 printf("\tDestination: " MACSTR "\n", MAC2STR(to));
623
624 libwifi_dump_action(&action, buf, buf_sz);
625 inject_frame(buf, buf_sz);
626
627 free(buf);
628
629 usleep(1e4); // 10ms
630 }
631 sleep(1);
632 }
633}
634
635void inject_actions() {
636 while (1) {
637 printf("Sending 50 action frames, then sleeping for 1 second\n");
638 for (int i = 0; i < 50; ++i) {
639 struct libwifi_action action;
640 memset(&action, 0, sizeof(struct libwifi_action));
641
642 libwifi_create_action(&action, to, from, ACTION_FAST_BSS_TRANSITION);
643
644 unsigned char *action_buf = malloc(256);
645 memset(action_buf, 0, 256);
646
647 size_t offset = 0;
648 size_t w = 0;
649
650 memcpy(action_buf, "\x01", 1); // Fast BSS Request
651 offset += 1;
652 memcpy(action_buf + offset, "\xAA\xBB\xCC\xDD\xEE\xFF", 6); // STA Address
653 offset += 6;
654 memcpy(action_buf + offset, "\xFF\xEE\xDD\xCC\xBB\xAA", 6); // AP Address
655 offset += 6;
656
657 unsigned char *tag_tmp = malloc(256);
658 memset(tag_tmp, 0, 256);
659
660 struct libwifi_tagged_parameter rsne = {0};
661 size_t tsz = libwifi_create_tag(&rsne, TAG_RSN, (const unsigned char * )"\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x04\x01\x00\x00\x0f\xac\x02\x00\x00", 20);
662 w = libwifi_dump_tag(&rsne, tag_tmp, tsz);
663 memcpy(action_buf + offset, tag_tmp, w);
664 offset += w;
665
666
667 struct libwifi_tagged_parameter mobdom = {0};
668 tsz = libwifi_create_tag(&mobdom, TAG_MOBILITY_DOMAIN, (const unsigned char*)"\x00\x11\x01", 3);
669 memset(tag_tmp, 0, tsz);
670 w = libwifi_dump_tag(&mobdom, tag_tmp, tsz);
671 memcpy(action_buf + offset, tag_tmp, w);
672 offset += w;
673 libwifi_free_tag(&mobdom);
674
675 struct libwifi_tagged_parameter fbss = {0};
676 tsz = libwifi_create_tag(&fbss, TAG_FAST_BSS_TRANSITION, (const unsigned char*)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xAA\xBB\xCC\xDD\xEE\xFF\xAA\xBB\xCC\xDD\xEE\xFF\xAA\xBB\xCC\xDD\xEE\xFF\xAA\xBB\xCC\xDD\xEE\xFF\xAA\xBB\xCC\xDD\xEE\xFF\xAA\x03\x04\xAA\xBB\x04\xAA\xBB\xCC\xDD", 88);
677 memset(tag_tmp, 0, tsz);
678 w = libwifi_dump_tag(&fbss, tag_tmp, tsz);
679 memcpy(action_buf + offset, tag_tmp, w);
680 offset += w;
681 libwifi_free_tag(&fbss);
682
683 libwifi_add_action_detail(&action.fixed_parameters.details, action_buf, offset);
684
685 unsigned char *buf = NULL;
686 size_t buf_sz = libwifi_get_action_length(&action);
687
688 buf = malloc(buf_sz);
689 if (buf == NULL) {
690 printf("malloc failure: %s", strerror(errno));
691 exit(EXIT_FAILURE);
692 }
693
694 printf("Injecting actions with:\n");
695 printf("\tAction: %d\n", ACTION_FAST_BSS_TRANSITION);
696 printf("\tSource: " MACSTR "\n", MAC2STR(from));
697 printf("\tDestination: " MACSTR "\n", MAC2STR(to));
698
699 libwifi_dump_action(&action, buf, buf_sz);
700 inject_frame(buf, buf_sz);
701
702 free(buf);
703
704 usleep(1e4); // 10ms
705 }
706 sleep(1);
707 }
708}
709
710void inject_atim() {
711 while (1) {
712 printf("Sending 50 ATIM frames, then sleeping for 1 second\n");
713 for (int i = 0; i < 50; ++i) {
714 struct libwifi_atim atim = {0};
715
716 libwifi_create_atim(&atim, to, from, from);
717
718 inject_frame(&atim, sizeof(struct libwifi_atim));
719
720 usleep(1e4); // 10ms
721 }
722 sleep(1);
723 }
724}
725
726void inject_rts() {
727 while (1) {
728 printf("Sending 50 RTS frames, then sleeping for 1 second\n");
729 for (int i = 0; i < 50; ++i) {
730 struct libwifi_rts rts = {0};
731
732 libwifi_create_rts(&rts, to, from, 32);
733
734 inject_frame(&rts, sizeof(struct libwifi_rts));
735
736 usleep(1e4); // 10ms
737 }
738 sleep(1);
739 }
740}
741
742void inject_cts() {
743 while (1) {
744 printf("Sending 50 CTS frames, then sleeping for 1 second\n");
745 for (int i = 0; i < 50; ++i) {
746 struct libwifi_cts cts = {0};
747
748 libwifi_create_cts(&cts, to, 32);
749
750 inject_frame(&cts, sizeof(struct libwifi_cts));
751
752 usleep(1e4); // 10ms
753 }
754 sleep(1);
755 }
756}
757
758void help(const char *name) {
759 fprintf(stderr, "Usage:\n");
760 fprintf(stderr, "\t%s --interface [interface] [--mode]\n", name);
761 fprintf(stderr, "\t\tor\n");
762 fprintf(stderr, "\t%s --file [output file] [--mode]\n", name);
763 fprintf(stderr, "\n");
764 fprintf(stderr, "Modes:\n");
765 fprintf(stderr, "\t--beacon\n");
766 fprintf(stderr, "\t--random-beacon\n");
767 fprintf(stderr, "\t--probe-req\n");
768 fprintf(stderr, "\t--probe-resp\n");
769 fprintf(stderr, "\t--deauth\n");
770 fprintf(stderr, "\t--disassoc\n");
771 fprintf(stderr, "\t--assoc-req\n");
772 fprintf(stderr, "\t--assoc-resp\n");
773 fprintf(stderr, "\t--reassoc-req\n");
774 fprintf(stderr, "\t--reassoc-resp\n");
775 fprintf(stderr, "\t--auth\n");
776 fprintf(stderr, "\t--timing-ad\n");
777 fprintf(stderr, "\t--atim\n");
778 fprintf(stderr, "\t--rts\n");
779 fprintf(stderr, "\t--cts\n");
780}
781
782void handle_args(int argc, const char *argv[]) {
783 char errbuf[PCAP_ERRBUF_SIZE];
784 memset(errbuf, 0, PCAP_ERRBUF_SIZE);
785
786 if (argc < 4) {
787 help(argv[0]);
788 exit(EXIT_SUCCESS);
789 }
790
791 if (strcmp(argv[1], "--file") == 0) {
792 inject_mode = OFFLINE_DUMP;
793
794 filename = fopen(argv[2], "w+");
795 if ((handle = pcap_open_dead(DLT_IEEE802_11_RADIO, BUFSIZ)) == NULL) {
796 fprintf(stderr, "1 %s: %s\n", argv[2], errbuf);
797 exit(EXIT_FAILURE);
798 }
799 if ((outputHandle = pcap_dump_fopen(handle, filename)) == NULL) {
800 fprintf(stderr, "2 %s: %s\n", argv[2], errbuf);
801 exit(EXIT_FAILURE);
802 }
803 } else if (strcmp(argv[1], "--interface") == 0) {
804 inject_mode = LIVE_INJECT;
805
806 if ((handle = pcap_create(argv[2], errbuf)) == NULL) {
807 fprintf(stderr, "Couldn't open interface %s: %s\n", argv[2], errbuf);
808 exit(EXIT_FAILURE);
809 }
810 if (pcap_activate(handle) == 0) {
811 printf("Sniffing on %s\n", argv[2]);
812 } else {
813 fprintf(stderr, "Couldn't activate %s: %s\n", argv[2], pcap_geterr(handle));
814 exit(EXIT_FAILURE);
815 }
816 } else {
817 help(argv[0]);
818 exit(EXIT_SUCCESS);
819 }
820
821 if (strcmp(argv[3], "--beacon") == 0) {
822 mode = MODE_BEACON;
823 } else if (strcmp(argv[3], "--random-beacon") == 0) {
824 mode = MODE_RANDOM_BEACON;
825 } else if (strcmp(argv[3], "--probe-resp") == 0) {
826 mode = MODE_PROBE_RESPONSE;
827 } else if (strcmp(argv[3], "--probe-req") == 0) {
828 mode = MODE_PROBE_REQUEST;
829 } else if (strcmp(argv[3], "--deauth") == 0) {
830 mode = MODE_DEAUTH;
831 } else if (strcmp(argv[3], "--disassoc") == 0) {
832 mode = MODE_DISASSOC;
833 } else if (strcmp(argv[3], "--assoc-resp") == 0) {
834 mode = MODE_ASSOC_RESPONSE;
835 } else if (strcmp(argv[3], "--assoc-req") == 0) {
836 mode = MODE_ASSOC_REQUEST;
837 } else if (strcmp(argv[3], "--reassoc-resp") == 0) {
838 mode = MODE_REASSOC_RESPONSE;
839 } else if (strcmp(argv[3], "--reassoc-req") == 0) {
840 mode = MODE_REASSOC_REQUEST;
841 } else if (strcmp(argv[3], "--auth") == 0) {
842 mode = MODE_AUTH;
843 } else if (strcmp(argv[3], "--timing-ad") == 0) {
844 mode = MODE_TIMING_AD;
845 } else if (strcmp(argv[3], "--action") == 0) {
846 mode = MODE_ACTION;
847 } else if (strcmp(argv[3], "--action-noack") == 0) {
848 mode = MODE_ACTION_NOACK;
849 } else if (strcmp(argv[3], "--atim") == 0) {
850 mode = MODE_ATIM;
851 } else if (strcmp(argv[3], "--rts") == 0) {
852 mode = MODE_RTS;
853 } else if (strcmp(argv[3], "--cts") == 0) {
854 mode = MODE_CTS;
855 } else {
856 help(argv[0]);
857 exit(EXIT_SUCCESS);
858 }
859}
860
861int main(int argc, const char *argv[]) {
862 signal(SIGINT, handle_interupt);
863 handle_args(argc, argv);
864
865 printf("Starting in 5 seconds...\n");
866
867 sleep(5);
868
869 switch (mode) {
870 case MODE_BEACON:
871 inject_beacons(0);
872 break;
873 case MODE_RANDOM_BEACON:
874 inject_beacons(1);
875 break;
876 case MODE_PROBE_RESPONSE:
877 inject_probe_responses();
878 break;
879 case MODE_PROBE_REQUEST:
880 inject_probe_requests();
881 break;
882 case MODE_DEAUTH:
883 inject_deauths();
884 break;
885 case MODE_DISASSOC:
886 inject_disassocs();
887 break;
888 case MODE_ASSOC_REQUEST:
889 inject_assoc_requests();
890 break;
891 case MODE_ASSOC_RESPONSE:
892 inject_assoc_responses();
893 break;
894 case MODE_REASSOC_REQUEST:
895 inject_reassoc_requests();
896 break;
897 case MODE_REASSOC_RESPONSE:
898 inject_reassoc_responses();
899 break;
900 case MODE_AUTH:
901 inject_auths();
902 break;
903 case MODE_ACTION:
904 inject_actions();
905 break;
906 case MODE_ACTION_NOACK:
907 inject_action_noacks();
908 break;
909 case MODE_TIMING_AD:
910 inject_timing_ads();
911 break;
912 case MODE_ATIM:
913 inject_atim();
914 break;
915 case MODE_RTS:
916 inject_rts();
917 break;
918 case MODE_CTS:
919 inject_cts();
920 break;
921 }
922
923 return 0;
924}
diff --git a/test/src/test_misc.c b/test/src/test_misc.c new file mode 100644 index 0000000..f103455 --- /dev/null +++ b/test/src/test_misc.c
@@ -0,0 +1,30 @@
1#include <libwifi.h>
2#include <libwifi/core/core.h>
3#include <stdio.h>
4
5void gen_macs() {
6 printf("Getting 10 random MAC addresses:\n");
7 for(int i = 0; i < 10; i++) {
8 unsigned char mac[6] = {0};
9 libwifi_random_mac(mac, NULL);
10 printf(MACSTR "\n", MAC2STR(mac));
11 }
12
13 printf("Generating 10 random MAC addresses with 00:20:91 OUI:\n");
14 for(int i = 0; i < 10; i++) {
15 unsigned char mac[6] = {0};
16 libwifi_random_mac(mac, (unsigned char *) "\x00\x20\x91");
17 printf(MACSTR "\n", MAC2STR(mac));
18 }
19 printf("\n");
20}
21
22int main() {
23 libwifi_dummy();
24
25 printf("libwifi version: %s\n\n", libwifi_get_version());
26
27 gen_macs();
28
29 return 0;
30}
diff --git a/test/src/test_parsing.c b/test/src/test_parsing.c new file mode 100644 index 0000000..c345346 --- /dev/null +++ b/test/src/test_parsing.c
@@ -0,0 +1,613 @@
1#include "helpers.h"
2#include <errno.h>
3#include <libwifi.h>
4#include <pcap.h>
5#include <pcap/pcap.h>
6#include <stddef.h>
7#include <stdint.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11#include <sys/types.h>
12
13#define PCAP_SAVEFILE "/tmp/debug.pcap"
14#define FILTER ""
15#define MODE_BEACON 1
16#define MODE_PROBE_RESPONSE 2
17#define MODE_PROBE_REQUEST 3
18#define MODE_EAPOL 4
19#define MODE_DEAUTH 5
20#define MODE_DISASSOC 6
21#define MODE_ASSOC_RESPONSE 7
22#define MODE_ASSOC_REQUEST 8
23#define MODE_REASSOC_REQUEST 9
24#define MODE_REASSOC_RESPONSE 10
25#define MODE_DATA 11
26#define MODE_ALL 99
27
28static pcap_t *handle;
29pcap_dumper_t *pd;
30static struct bpf_program *filter;
31static int got_radiotap;
32static unsigned long packet_num = 0;
33static int mode = 0;
34static int parse_radiotap_header = 0;
35
36struct libwifi_bss bss = {0};
37struct libwifi_sta sta = {0};
38
39void help(const char *);
40void parse_packet(unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet);
41void print_bss_info(struct libwifi_bss *bss);
42void print_sta_info(struct libwifi_sta *sta);
43void print_tag_info(unsigned char *data, size_t data_len);
44
45void interrupted(int signum) {
46 pcap_dump_close(pd);
47 pcap_close(handle);
48}
49
50void print_bss_info(struct libwifi_bss *bss) {
51 if (bss == NULL) {
52 return;
53 }
54
55 printf("=== BSS Parsing ===\n");
56 printf("ESSID: %s\n", bss->hidden ? "(hidden)" : bss->ssid);
57 printf("BSSID: " MACSTR "\n", MAC2STR(bss->bssid));
58 printf("Receiver: " MACSTR "\n", MAC2STR(bss->receiver));
59 printf("Transmitter: " MACSTR "\n", MAC2STR(bss->transmitter));
60 printf("Channel: %d\n", bss->channel);
61 printf("WPS: %s\n", bss->wps ? "yes" : "no");
62
63 char sec_buf[LIBWIFI_SECURITY_BUF_LEN];
64 libwifi_get_security_type(bss, sec_buf);
65 printf("Encryption: %s\n", sec_buf);
66
67 libwifi_get_group_ciphers(bss, sec_buf);
68 printf("\tGroup Ciphers: %s\n", sec_buf);
69
70 libwifi_get_pairwise_ciphers(bss, sec_buf);
71 printf("\tPairwise Ciphers: %s\n", sec_buf);
72
73 libwifi_get_auth_key_suites(bss, sec_buf);
74 printf("\tAuth Key Suites: %s\n", sec_buf);
75
76 if (bss->rsn_info.rsn_capabilities & LIBWIFI_RSN_CAPAB_MFP_CAPABLE) {
77 printf("\tMFP Capable: Yes\n");
78 }
79 if (bss->rsn_info.rsn_capabilities & LIBWIFI_RSN_CAPAB_MFP_REQUIRED) {
80 printf("\tMFP Required: Yes\n");
81 }
82
83 if (bss->tags.length) {
84 printf("Tagged Parameters:\n");
85 print_tag_info(bss->tags.parameters, bss->tags.length);
86 } else {
87 printf("Tagged Parameters: None\n");
88 }
89
90 printf("=== BSS End ===\n");
91 printf("\n\n");
92}
93
94void print_sta_info(struct libwifi_sta *sta) {
95 if (sta == NULL) {
96 return;
97 }
98
99 printf("=== STA Parsing ===\n");
100
101 if (sta->broadcast_ssid) {
102 printf("ESSID: <broadcast>\n");
103 } else {
104 printf("ESSID: %s\n", sta->ssid);
105 }
106 printf("Channel: %u\n", sta->channel);
107 printf("BSSID: " MACSTR "\n", MAC2STR(sta->bssid));
108 printf("MAC: " MACSTR "\n", MAC2STR(sta->transmitter));
109
110 printf("=== STA End ===\n");
111 printf("\n\n");
112}
113
114void print_tag_info(unsigned char *data, size_t data_len) {
115 struct libwifi_tag_iterator it;
116 if (libwifi_tag_iterator_init(&it, data, data_len) != 0) {
117 printf("Couldn't initialise tag iterator\n");
118 return;
119 }
120 do {
121 printf("\tTag: %d (Size: %d)\n", it.tag_header->tag_num, it.tag_header->tag_len);
122
123 int max_size = 16;
124 if (it.tag_header->tag_len < 16) {
125 max_size = it.tag_header->tag_len;
126 }
127 printf("\t%d bytes of Tag Data: ", max_size);
128 for (size_t i = 0; i < max_size; i++) {
129 printf("%02x ", it.tag_data[i]);
130 }
131 printf("\n");
132 } while (libwifi_tag_iterator_next(&it) != -1);
133}
134
135void parse_radiotap(const unsigned char *packet) {
136 struct libwifi_radiotap_info rtap_info;
137 libwifi_parse_radiotap_info(&rtap_info, packet);
138
139 printf("=== Radiotap Parsing ===\n");
140 printf("Radiotap Channel: %d\n", rtap_info.channel.freq);
141 printf("Radiotap Channel Flags: 0x%04x\n", rtap_info.channel.flags);
142 printf("Radiotap Rate: %.2f Mb/s\n", rtap_info.rate);
143 printf("Radiotap Rate Raw: 0x%02x\n", rtap_info.rate_raw);
144 printf("Radiotap Signal: %d dBm\n", rtap_info.signal);
145 for (int i = 0; i < rtap_info.antenna_count; i++) {
146 printf("Radiotap Antenna %d: %d dBm\n", rtap_info.antennas[i].antenna_number, rtap_info.antennas[i].signal);
147 }
148 printf("Radiotap Flags: 0x%04x\n", rtap_info.flags);
149 printf("Radiotap Extended Flags: 0x%08x\n", rtap_info.extended_flags);
150 printf("Radiotap RX Flags: 0x%04x\n", rtap_info.rx_flags);
151 printf("Radiotap TX Flags: 0x%04x\n", rtap_info.tx_flags);
152 printf("Radiotap TX Power: %d\n", rtap_info.tx_power);
153 printf("Radiotap RTS Retries: %d\n", rtap_info.rts_retries);
154 printf("Radiotap Data Retries: %d\n", rtap_info.data_retries);
155 printf("=== Radiotap End ===\n");
156}
157
158void parse_beacon(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) {
159 if (frame.frame_control.type == TYPE_MANAGEMENT && frame.frame_control.subtype == SUBTYPE_BEACON) {
160 printf("Packet : %lu\n", packet_num);
161 int ret = libwifi_parse_beacon(&bss, &frame);
162 if (ret != 0) {
163 printf("Failed to parse beacon: %d\n", ret);
164 pcap_dump(args, header, packet);
165 return;
166 }
167
168 if (got_radiotap && parse_radiotap_header) {
169 parse_radiotap(packet);
170 }
171
172 print_bss_info(&bss);
173 }
174}
175
176void parse_probe_request(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) {
177 if (frame.frame_control.type == TYPE_MANAGEMENT && frame.frame_control.subtype == SUBTYPE_PROBE_REQ) {
178 printf("Packet : %lu\n", packet_num);
179 int ret = libwifi_parse_probe_req(&sta, &frame);
180 if (ret != 0) {
181 printf("Failed to parse probe request: %d\n", ret);
182 pcap_dump(args, header, packet);
183 return;
184 }
185
186 if (got_radiotap && parse_radiotap_header) {
187 parse_radiotap(packet);
188 }
189
190 print_sta_info(&sta);
191 }
192}
193void parse_probe_response(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) {
194 if (frame.frame_control.type == TYPE_MANAGEMENT && frame.frame_control.subtype == SUBTYPE_PROBE_RESP) {
195 printf("Packet : %lu\n", packet_num);
196 int ret = libwifi_parse_probe_resp(&bss, &frame);
197 if (ret != 0) {
198 printf("Failed to parse probe response: %d\n", ret);
199 pcap_dump(args, header, packet);
200 return;
201 }
202
203 if (got_radiotap && parse_radiotap_header) {
204 parse_radiotap(packet);
205 }
206
207 print_bss_info(&bss);
208 }
209}
210void parse_deauth(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) {
211 if (frame.frame_control.type == TYPE_MANAGEMENT && frame.frame_control.subtype == SUBTYPE_DEAUTH) {
212 printf("Packet : %lu\n", packet_num);
213 struct libwifi_parsed_deauth deauth;
214 int ret = libwifi_parse_deauth(&deauth, &frame);
215 if (ret != 0) {
216 printf("Failed to parse deauthentication: %d\n", ret);
217 pcap_dump(args, header, packet);
218 return;
219 }
220
221 if (got_radiotap && parse_radiotap_header) {
222 parse_radiotap(packet);
223 }
224
225 printf("=== Deauthentication Frame ===\n");
226 if (deauth.ordered) {
227 printf("Address 1: " MACSTR "\n", MAC2STR(deauth.frame_header.ordered.addr1));
228 printf("Address 2: " MACSTR "\n", MAC2STR(deauth.frame_header.ordered.addr2));
229 printf("Address 3: " MACSTR "\n", MAC2STR(deauth.frame_header.ordered.addr3));
230 } else {
231 printf("Address 1: " MACSTR "\n", MAC2STR(deauth.frame_header.unordered.addr1));
232 printf("Address 2: " MACSTR "\n", MAC2STR(deauth.frame_header.unordered.addr2));
233 printf("Address 3: " MACSTR "\n", MAC2STR(deauth.frame_header.unordered.addr3));
234 }
235
236 printf("Reason: %d (0x%04x)\n", deauth.fixed_parameters.reason_code, deauth.fixed_parameters.reason_code);
237
238 if (deauth.tags.length) {
239 printf("Tagged Parameters:\n");
240 print_tag_info(deauth.tags.parameters, deauth.tags.length);
241 } else {
242 printf("Tagged Parameters: None\n");
243 }
244
245 printf("=== End Deauthentication Frame ===\n");
246 printf("\n\n");
247 }
248}
249void parse_disassoc(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) {
250 if (frame.frame_control.type == TYPE_MANAGEMENT && frame.frame_control.subtype == SUBTYPE_DISASSOC) {
251 printf("Packet : %lu\n", packet_num);
252 struct libwifi_parsed_disassoc disassoc;
253 int ret = libwifi_parse_disassoc(&disassoc, &frame);
254 if (ret != 0) {
255 printf("Failed to parse diassociation: %d\n", ret);
256 pcap_dump(args, header, packet);
257 return;
258 }
259
260 if (got_radiotap && parse_radiotap_header) {
261 parse_radiotap(packet);
262 }
263
264 printf("=== Disassociation Frame ===\n");
265 if (disassoc.ordered) {
266 printf("Address 1: " MACSTR "\n", MAC2STR(disassoc.frame_header.ordered.addr1));
267 printf("Address 2: " MACSTR "\n", MAC2STR(disassoc.frame_header.ordered.addr2));
268 printf("Address 3: " MACSTR "\n", MAC2STR(disassoc.frame_header.ordered.addr3));
269 } else {
270 printf("Address 1: " MACSTR "\n", MAC2STR(disassoc.frame_header.unordered.addr1));
271 printf("Address 2: " MACSTR "\n", MAC2STR(disassoc.frame_header.unordered.addr2));
272 printf("Address 3: " MACSTR "\n", MAC2STR(disassoc.frame_header.unordered.addr3));
273 }
274
275 printf("Reason: %d (0x%04x)\n", disassoc.fixed_parameters.reason_code, disassoc.fixed_parameters.reason_code);
276
277 printf("Tagged Parameters:\n");
278 if (disassoc.tags.length == 0) {
279 printf("\tNo Tags\n");
280 } else {
281 printf("\tTags Found\n");
282 }
283
284 printf("=== End Disassociation Frame ===\n");
285 printf("\n\n");
286 }
287}
288void parse_assoc_request(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) {
289 if (frame.frame_control.type == TYPE_MANAGEMENT && frame.frame_control.subtype == SUBTYPE_ASSOC_REQ) {
290 printf("Packet : %lu\n", packet_num);
291 int ret = libwifi_parse_assoc_req(&sta, &frame);
292 if (ret != 0) {
293 printf("Failed to parse association request: %d\n", ret);
294 pcap_dump(args, header, packet);
295 return;
296 }
297
298 if (got_radiotap && parse_radiotap_header) {
299 parse_radiotap(packet);
300 }
301
302 print_sta_info(&sta);
303 }
304}
305void parse_assoc_response(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) {
306 if (frame.frame_control.type == TYPE_MANAGEMENT && frame.frame_control.subtype == SUBTYPE_ASSOC_RESP) {
307 printf("Packet : %lu\n", packet_num);
308 int ret = libwifi_parse_assoc_resp(&bss, &frame);
309 if (ret != 0) {
310 printf("Failed to parse association response: %d\n", ret);
311 pcap_dump(args, header, packet);
312 return;
313 }
314
315 if (got_radiotap && parse_radiotap_header) {
316 parse_radiotap(packet);
317 }
318
319 print_bss_info(&bss);
320 }
321}
322void parse_reassoc_request(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) {
323 if (frame.frame_control.type == TYPE_MANAGEMENT && frame.frame_control.subtype == SUBTYPE_REASSOC_REQ) {
324 printf("Packet : %lu\n", packet_num);
325 int ret = libwifi_parse_reassoc_req(&sta, &frame);
326 if (ret != 0) {
327 printf("Failed to parse reassociation request: %d\n", ret);
328 pcap_dump(args, header, packet);
329 return;
330 }
331
332 if (got_radiotap && parse_radiotap_header) {
333 parse_radiotap(packet);
334 }
335
336 print_sta_info(&sta);
337 }
338}
339void parse_reassoc_response(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) {
340 if (frame.frame_control.type == TYPE_MANAGEMENT && frame.frame_control.subtype == SUBTYPE_REASSOC_RESP) {
341 printf("Packet : %lu\n", packet_num);
342 int ret = libwifi_parse_reassoc_resp(&bss, &frame);
343 if (ret != 0) {
344 printf("Failed to parse reassociation response: %d\n", ret);
345 pcap_dump(args, header, packet);
346 return;
347 }
348
349 if (got_radiotap && parse_radiotap_header) {
350 parse_radiotap(packet);
351 }
352
353 print_bss_info(&bss);
354 }
355}
356void parse_data_eapol(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) {
357 if (frame.frame_control.type == TYPE_DATA) {
358 if (libwifi_check_wpa_handshake(&frame) > 0) {
359 printf("=== EAPOL ===\n");
360 printf("WPA Handshake\n");
361 int part = libwifi_check_wpa_message(&frame);
362 printf("WPA Handshake Message: %s\n", libwifi_get_wpa_message_string(&frame));
363
364 struct libwifi_wpa_auth_data data = {0};
365 libwifi_get_wpa_data(&frame, &data);
366
367 printf("EAPOL: Version: %d\n", data.version);
368 printf("EAPOL: Type: %d\n", data.type);
369 printf("EAPOL: Length: %d\n", data.length);
370 printf("EAPOL: Descriptor: %d\n", data.descriptor);
371 printf("EAPOL: Key Info: Information: 0x%04x\n", data.key_info.information);
372 printf("EAPOL: Key Info: Key Length: %d\n", data.key_info.key_length);
373 printf("EAPOL: Key Info: Replay Counter: %lu\n", data.key_info.replay_counter);
374 printf("EAPOL: Key Info: Nonce: ");
375 for (size_t i = 0; i < sizeof(data.key_info.nonce); ++i) printf("%02x ", data.key_info.nonce[i]);
376 printf("\n");
377 printf("EAPOL: Key Info: IV: ");
378 for (size_t i = 0; i < sizeof(data.key_info.iv); ++i) printf("%02x ", data.key_info.iv[i]);
379 printf("\n");
380 printf("EAPOL: Key Info: RSC: ");
381 for (size_t i = 0; i < sizeof(data.key_info.rsc); ++i) printf("%02x ", data.key_info.rsc[i]);
382 printf("\n");
383 printf("EAPOL: Key Info: ID: ");
384 for (size_t i = 0; i < sizeof(data.key_info.id); ++i) printf("%02x ", data.key_info.id[i]);
385 printf("\n");
386 printf("EAPOL: Key Info: MIC: ");
387 for (size_t i = 0; i < sizeof(data.key_info.mic); ++i) printf("%02x ", data.key_info.mic[i]);
388 printf("\n");
389 printf("EAPOL: Key Info: Key Data Length: %d\n", data.key_info.key_data_length);
390 if (data.key_info.key_data_length) {
391 printf("EAPOL: Key Info: Key Data: ");
392 for (size_t i = 0; i < data.key_info.key_data_length; ++i) printf("%02x ", data.key_info.key_data[i]);
393 printf("\n");
394 }
395
396 libwifi_free_wpa_data(&data);
397
398 printf("\n\n");
399 }
400 }
401}
402
403void parse_data(struct libwifi_frame frame, unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) {
404 if (frame.frame_control.type == TYPE_DATA) {
405 if (frame.flags & LIBWIFI_FLAGS_IS_QOS) {
406 printf("Receiver: " MACSTR "\n", MAC2STR(frame.header.data_qos.addr1));
407 printf("Transmitter: " MACSTR "\n", MAC2STR(frame.header.data_qos.addr2));
408 } else {
409 printf("Receiver: " MACSTR "\n", MAC2STR(frame.header.data.addr1));
410 printf("Transmitter: " MACSTR "\n", MAC2STR(frame.header.data.addr2));
411 }
412 printf("Body Length: %zu\n", frame.len - frame.header_len);
413 printf("Body:\n");
414 hexdump(frame.body, frame.len - frame.header_len);
415 }
416}
417
418void parse_packet(unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet) {
419 ++packet_num;
420 unsigned long data_len = header->caplen;
421 unsigned char *data = (unsigned char *) packet;
422
423 struct libwifi_frame frame = {0};
424 int ret = libwifi_get_wifi_frame(&frame, data, data_len, 1);
425 if (ret != 0) {
426 printf("[!] Error getting libwifi_frame: %d\n", ret);
427 return;
428 }
429
430 memset(&bss, 0, sizeof(struct libwifi_bss));
431 memset(&sta, 0, sizeof(struct libwifi_sta));
432
433 switch (mode) {
434 case MODE_BEACON:
435 parse_beacon(frame, args, header, packet);
436 break;
437 case MODE_PROBE_REQUEST:
438 parse_probe_request(frame, args, header, packet);
439 break;
440 case MODE_PROBE_RESPONSE:
441 parse_probe_response(frame, args, header, packet);
442 break;
443 case MODE_DEAUTH:
444 parse_deauth(frame, args, header, packet);
445 break;
446 case MODE_DISASSOC:
447 parse_disassoc(frame, args, header, packet);
448 break;
449 case MODE_ASSOC_REQUEST:
450 parse_assoc_request(frame, args, header, packet);
451 break;
452 case MODE_ASSOC_RESPONSE:
453 parse_assoc_response(frame, args, header, packet);
454 break;
455 case MODE_REASSOC_REQUEST:
456 parse_reassoc_request(frame, args, header, packet);
457 break;
458 case MODE_REASSOC_RESPONSE:
459 parse_reassoc_response(frame, args, header, packet);
460 break;
461 case MODE_EAPOL:
462 parse_data_eapol(frame, args, header, packet);
463 break;
464 case MODE_DATA:
465 parse_data(frame, args, header, packet);
466 break;
467 case MODE_ALL:
468 parse_beacon(frame, args, header, packet);
469 parse_probe_request(frame, args, header, packet);
470 parse_probe_response(frame, args, header, packet);
471 parse_deauth(frame, args, header, packet);
472 parse_disassoc(frame, args, header, packet);
473 parse_assoc_request(frame, args, header, packet);
474 parse_assoc_response(frame, args, header, packet);
475 parse_reassoc_request(frame, args, header, packet);
476 parse_reassoc_response(frame, args, header, packet);
477 parse_data_eapol(frame, args, header, packet);
478 parse_data(frame, args, header, packet);
479 default:
480 break;
481 }
482
483 libwifi_free_bss(&bss);
484 libwifi_free_wifi_frame(&frame);
485}
486
487void help(const char *name) {
488 fprintf(stderr, "Usage:\n");
489 fprintf(stderr, "\t%s --interface [interface] [--mode] [--radiotap]\n", name);
490 fprintf(stderr, "\t\tor\n");
491 fprintf(stderr, "\t%s --file [capture file] [--mode] [--radiotap]\n", name);
492 fprintf(stderr, "\n");
493 fprintf(stderr, "Modes:\n");
494 fprintf(stderr, "\t--beacon\n");
495 fprintf(stderr, "\t--probe-req\n");
496 fprintf(stderr, "\t--probe-resp\n");
497 fprintf(stderr, "\t--deauth\n");
498 fprintf(stderr, "\t--disassoc\n");
499 fprintf(stderr, "\t--assoc-req\n");
500 fprintf(stderr, "\t--assoc-resp\n");
501 fprintf(stderr, "\t--reassoc-req\n");
502 fprintf(stderr, "\t--reassoc-resp\n");
503 fprintf(stderr, "\t--eapol\n");
504}
505
506void handle_args(int argc, const char *argv[]) {
507 char errbuf[PCAP_ERRBUF_SIZE];
508
509 if (argc < 4) {
510 help(argv[0]);
511 exit(EXIT_SUCCESS);
512 }
513
514 if (strcmp(argv[1], "--file") == 0) {
515 if ((handle = pcap_open_offline(argv[2], errbuf)) == NULL) {
516 fprintf(stderr, "Couldn't read file %s: %s\n", argv[2], errbuf);
517 exit(EXIT_FAILURE);
518 }
519 } else if (strcmp(argv[1], "--interface") == 0) {
520 if ((handle = pcap_create(argv[2], errbuf)) == NULL) {
521 fprintf(stderr, "Failed to open interface \"%s\" for sniffing: %s\n", argv[2], errbuf);
522 exit(EXIT_FAILURE);
523 }
524 if (pcap_activate(handle) == 0) {
525 printf("[+] Started sniffing on %s\n", argv[2]);
526 } else {
527 fprintf(stderr, "[!] Couldn't activate capture: %s.\n", pcap_geterr(handle));
528 pcap_close(handle);
529 exit(EXIT_FAILURE);
530 }
531 } else {
532 help(argv[0]);
533 exit(EXIT_SUCCESS);
534 }
535
536 if (strcmp(argv[3], "--beacon") == 0) {
537 mode = MODE_BEACON;
538 } else if (strcmp(argv[3], "--probe-req") == 0) {
539 mode = MODE_PROBE_REQUEST;
540 } else if (strcmp(argv[3], "--probe-resp") == 0) {
541 mode = MODE_PROBE_RESPONSE;
542 } else if (strcmp(argv[3], "--deauth") == 0) {
543 mode = MODE_DEAUTH;
544 } else if (strcmp(argv[3], "--disassoc") == 0) {
545 mode = MODE_DISASSOC;
546 } else if (strcmp(argv[3], "--assoc-req") == 0) {
547 mode = MODE_ASSOC_REQUEST;
548 } else if (strcmp(argv[3], "--assoc-resp") == 0) {
549 mode = MODE_ASSOC_RESPONSE;
550 } else if (strcmp(argv[3], "--reassoc-req") == 0) {
551 mode = MODE_REASSOC_REQUEST;
552 } else if (strcmp(argv[3], "--reassoc-resp") == 0) {
553 mode = MODE_REASSOC_RESPONSE;
554 } else if (strcmp(argv[3], "--eapol") == 0) {
555 mode = MODE_EAPOL;
556 } else if (strcmp(argv[3], "--data") == 0) {
557 mode = MODE_DATA;
558 } else if (strcmp(argv[3], "--all") == 0) {
559 mode = MODE_ALL;
560 } else {
561 help(argv[0]);
562 exit(EXIT_SUCCESS);
563 }
564
565 if (argc > 4) {
566 if (strcmp(argv[4], "--radiotap") == 0) {
567 parse_radiotap_header = 1;
568 }
569 }
570}
571
572int main(int argc, const char *argv[]) {
573 packet_num = 0;
574 char errbuf[PCAP_ERRBUF_SIZE];
575
576 handle_args(argc, argv);
577
578 int linktype = pcap_datalink(handle);
579 if (linktype == DLT_IEEE802_11_RADIO) {
580 got_radiotap = 1;
581 } else if (linktype == DLT_IEEE802_11) {
582 got_radiotap = 0;
583 } else {
584 fprintf(stderr, "[!] 802.11 and radiotap headers not provided (%d)\n", pcap_datalink(handle));
585 pcap_close(handle);
586 exit(EXIT_FAILURE);
587 }
588
589 if ((filter = malloc(sizeof(struct bpf_program))) == NULL) {
590 perror("Malloc failure");
591 pcap_close(handle);
592 exit(EXIT_FAILURE);
593 }
594 printf("[*] Compiling and optimizing frame filter, this can take a second\n");
595 if (pcap_compile(handle, filter, FILTER, 0, 0) != 0) {
596 fprintf(stderr, "[!] Couldn't compile filter: %s\n", pcap_geterr(handle));
597 pcap_close(handle);
598 free(filter);
599 exit(EXIT_FAILURE);
600 }
601 if (pcap_setfilter(handle, filter) != 0) {
602 fprintf(stderr, "[!] Couldn't set filter: %s\n", pcap_geterr(handle));
603 pcap_close(handle);
604 free(filter);
605 exit(EXIT_FAILURE);
606 }
607 printf("[+] Complete\n");
608
609 pd = pcap_dump_open(handle, PCAP_SAVEFILE);
610 pcap_loop(handle, -1 /*INFINITY*/, &parse_packet, (unsigned char *) pd);
611
612 return 0;
613}