From ae6c98a48da409d040604aeffb84a38155fb5bac Mon Sep 17 00:00:00 2001 From: Marc Date: Tue, 30 Nov 2021 22:39:26 +0000 Subject: Initial Commit Signed-off-by: Marc --- src/libwifi.h | 75 +++ src/libwifi/core/core.c | 46 ++ src/libwifi/core/core.h | 53 ++ src/libwifi/core/frame/control/cts.h | 35 ++ src/libwifi/core/frame/control/rts.h | 38 ++ src/libwifi/core/frame/crc.c | 63 ++ src/libwifi/core/frame/crc.h | 49 ++ src/libwifi/core/frame/data/data.h | 32 + src/libwifi/core/frame/frame.c | 145 +++++ src/libwifi/core/frame/frame.h | 334 ++++++++++ src/libwifi/core/frame/management/action.h | 93 +++ src/libwifi/core/frame/management/assoc_request.h | 51 ++ src/libwifi/core/frame/management/assoc_response.h | 54 ++ src/libwifi/core/frame/management/atim.h | 33 + src/libwifi/core/frame/management/authentication.h | 54 ++ src/libwifi/core/frame/management/beacon.h | 54 ++ src/libwifi/core/frame/management/common.h | 101 +++ .../core/frame/management/deauthentication.h | 55 ++ src/libwifi/core/frame/management/disassociation.h | 55 ++ src/libwifi/core/frame/management/probe_request.h | 38 ++ src/libwifi/core/frame/management/probe_response.h | 54 ++ .../core/frame/management/reassoc_request.h | 54 ++ .../core/frame/management/reassoc_response.h | 54 ++ src/libwifi/core/frame/management/timing_ad.h | 82 +++ src/libwifi/core/frame/tag.c | 131 ++++ src/libwifi/core/frame/tag.h | 306 +++++++++ src/libwifi/core/frame/tag_iterator.c | 55 ++ src/libwifi/core/frame/tag_iterator.h | 53 ++ src/libwifi/core/misc/byteswap.h | 31 + src/libwifi/core/misc/epoch.c | 23 + src/libwifi/core/misc/epoch.h | 26 + src/libwifi/core/misc/llc.h | 33 + src/libwifi/core/misc/radiotap.h | 83 +++ src/libwifi/core/misc/security.h | 289 +++++++++ src/libwifi/core/misc/types.h | 218 +++++++ src/libwifi/core/radiotap/COPYING | 14 + src/libwifi/core/radiotap/platform.h | 81 +++ src/libwifi/core/radiotap/radiotap.c | 469 ++++++++++++++ src/libwifi/core/radiotap/radiotap.h | 221 +++++++ src/libwifi/core/radiotap/radiotap_iter.h | 101 +++ src/libwifi/gen/control/cts.c | 30 + src/libwifi/gen/control/cts.h | 30 + src/libwifi/gen/control/rts.c | 32 + src/libwifi/gen/control/rts.h | 32 + src/libwifi/gen/management/action.c | 110 ++++ src/libwifi/gen/management/action.h | 80 +++ src/libwifi/gen/management/assoc_request.c | 85 +++ src/libwifi/gen/management/assoc_request.h | 39 ++ src/libwifi/gen/management/assoc_response.c | 106 ++++ src/libwifi/gen/management/assoc_response.h | 69 +++ src/libwifi/gen/management/atim.c | 35 ++ src/libwifi/gen/management/atim.h | 24 + src/libwifi/gen/management/authentication.c | 81 +++ src/libwifi/gen/management/authentication.h | 64 ++ src/libwifi/gen/management/beacon.c | 117 ++++ src/libwifi/gen/management/beacon.h | 78 +++ src/libwifi/gen/management/common.h | 54 ++ src/libwifi/gen/management/deauthentication.c | 82 +++ src/libwifi/gen/management/deauthentication.h | 63 ++ src/libwifi/gen/management/disassociation.c | 80 +++ src/libwifi/gen/management/disassociation.h | 63 ++ src/libwifi/gen/management/probe_request.c | 76 +++ src/libwifi/gen/management/probe_request.h | 64 ++ src/libwifi/gen/management/probe_response.c | 118 ++++ src/libwifi/gen/management/probe_response.h | 78 +++ src/libwifi/gen/management/reassoc_request.c | 87 +++ src/libwifi/gen/management/reassoc_request.h | 30 + src/libwifi/gen/management/reassoc_response.c | 108 ++++ src/libwifi/gen/management/reassoc_response.h | 70 +++ src/libwifi/gen/management/timing_ad.c | 111 ++++ src/libwifi/gen/management/timing_ad.h | 32 + src/libwifi/gen/misc/radiotap.c | 123 ++++ src/libwifi/gen/misc/radiotap.h | 31 + src/libwifi/parse/data/data.c | 48 ++ src/libwifi/parse/data/data.h | 26 + src/libwifi/parse/data/eapol.c | 190 ++++++ src/libwifi/parse/data/eapol.h | 91 +++ src/libwifi/parse/management/assoc_request.c | 79 +++ src/libwifi/parse/management/assoc_request.h | 32 + src/libwifi/parse/management/assoc_response.c | 92 +++ src/libwifi/parse/management/assoc_response.h | 35 ++ src/libwifi/parse/management/beacon.c | 91 +++ src/libwifi/parse/management/beacon.h | 35 ++ src/libwifi/parse/management/common.c | 192 ++++++ src/libwifi/parse/management/common.h | 70 +++ src/libwifi/parse/management/deauthentication.c | 74 +++ src/libwifi/parse/management/deauthentication.h | 25 + src/libwifi/parse/management/disassociation.c | 72 +++ src/libwifi/parse/management/disassociation.h | 25 + src/libwifi/parse/management/probe_request.c | 72 +++ src/libwifi/parse/management/probe_request.h | 32 + src/libwifi/parse/management/probe_response.c | 88 +++ src/libwifi/parse/management/probe_response.h | 35 ++ src/libwifi/parse/management/reassoc_request.c | 79 +++ src/libwifi/parse/management/reassoc_request.h | 32 + src/libwifi/parse/management/reassoc_response.c | 92 +++ src/libwifi/parse/management/reassoc_response.h | 35 ++ src/libwifi/parse/misc/radiotap.c | 126 ++++ src/libwifi/parse/misc/radiotap.h | 39 ++ src/libwifi/parse/misc/security.c | 685 +++++++++++++++++++++ src/libwifi/parse/misc/security.h | 124 ++++ 101 files changed, 8734 insertions(+) create mode 100644 src/libwifi.h create mode 100644 src/libwifi/core/core.c create mode 100644 src/libwifi/core/core.h create mode 100644 src/libwifi/core/frame/control/cts.h create mode 100644 src/libwifi/core/frame/control/rts.h create mode 100644 src/libwifi/core/frame/crc.c create mode 100644 src/libwifi/core/frame/crc.h create mode 100644 src/libwifi/core/frame/data/data.h create mode 100644 src/libwifi/core/frame/frame.c create mode 100644 src/libwifi/core/frame/frame.h create mode 100644 src/libwifi/core/frame/management/action.h create mode 100644 src/libwifi/core/frame/management/assoc_request.h create mode 100644 src/libwifi/core/frame/management/assoc_response.h create mode 100644 src/libwifi/core/frame/management/atim.h create mode 100644 src/libwifi/core/frame/management/authentication.h create mode 100644 src/libwifi/core/frame/management/beacon.h create mode 100644 src/libwifi/core/frame/management/common.h create mode 100644 src/libwifi/core/frame/management/deauthentication.h create mode 100644 src/libwifi/core/frame/management/disassociation.h create mode 100644 src/libwifi/core/frame/management/probe_request.h create mode 100644 src/libwifi/core/frame/management/probe_response.h create mode 100644 src/libwifi/core/frame/management/reassoc_request.h create mode 100644 src/libwifi/core/frame/management/reassoc_response.h create mode 100644 src/libwifi/core/frame/management/timing_ad.h create mode 100644 src/libwifi/core/frame/tag.c create mode 100644 src/libwifi/core/frame/tag.h create mode 100644 src/libwifi/core/frame/tag_iterator.c create mode 100644 src/libwifi/core/frame/tag_iterator.h create mode 100644 src/libwifi/core/misc/byteswap.h create mode 100644 src/libwifi/core/misc/epoch.c create mode 100644 src/libwifi/core/misc/epoch.h create mode 100644 src/libwifi/core/misc/llc.h create mode 100644 src/libwifi/core/misc/radiotap.h create mode 100644 src/libwifi/core/misc/security.h create mode 100644 src/libwifi/core/misc/types.h create mode 100644 src/libwifi/core/radiotap/COPYING create mode 100644 src/libwifi/core/radiotap/platform.h create mode 100644 src/libwifi/core/radiotap/radiotap.c create mode 100644 src/libwifi/core/radiotap/radiotap.h create mode 100644 src/libwifi/core/radiotap/radiotap_iter.h create mode 100644 src/libwifi/gen/control/cts.c create mode 100644 src/libwifi/gen/control/cts.h create mode 100644 src/libwifi/gen/control/rts.c create mode 100644 src/libwifi/gen/control/rts.h create mode 100644 src/libwifi/gen/management/action.c create mode 100644 src/libwifi/gen/management/action.h create mode 100644 src/libwifi/gen/management/assoc_request.c create mode 100644 src/libwifi/gen/management/assoc_request.h create mode 100644 src/libwifi/gen/management/assoc_response.c create mode 100644 src/libwifi/gen/management/assoc_response.h create mode 100644 src/libwifi/gen/management/atim.c create mode 100644 src/libwifi/gen/management/atim.h create mode 100644 src/libwifi/gen/management/authentication.c create mode 100644 src/libwifi/gen/management/authentication.h create mode 100644 src/libwifi/gen/management/beacon.c create mode 100644 src/libwifi/gen/management/beacon.h create mode 100644 src/libwifi/gen/management/common.h create mode 100644 src/libwifi/gen/management/deauthentication.c create mode 100644 src/libwifi/gen/management/deauthentication.h create mode 100644 src/libwifi/gen/management/disassociation.c create mode 100644 src/libwifi/gen/management/disassociation.h create mode 100644 src/libwifi/gen/management/probe_request.c create mode 100644 src/libwifi/gen/management/probe_request.h create mode 100644 src/libwifi/gen/management/probe_response.c create mode 100644 src/libwifi/gen/management/probe_response.h create mode 100644 src/libwifi/gen/management/reassoc_request.c create mode 100644 src/libwifi/gen/management/reassoc_request.h create mode 100644 src/libwifi/gen/management/reassoc_response.c create mode 100644 src/libwifi/gen/management/reassoc_response.h create mode 100644 src/libwifi/gen/management/timing_ad.c create mode 100644 src/libwifi/gen/management/timing_ad.h create mode 100644 src/libwifi/gen/misc/radiotap.c create mode 100644 src/libwifi/gen/misc/radiotap.h create mode 100644 src/libwifi/parse/data/data.c create mode 100644 src/libwifi/parse/data/data.h create mode 100644 src/libwifi/parse/data/eapol.c create mode 100644 src/libwifi/parse/data/eapol.h create mode 100644 src/libwifi/parse/management/assoc_request.c create mode 100644 src/libwifi/parse/management/assoc_request.h create mode 100644 src/libwifi/parse/management/assoc_response.c create mode 100644 src/libwifi/parse/management/assoc_response.h create mode 100644 src/libwifi/parse/management/beacon.c create mode 100644 src/libwifi/parse/management/beacon.h create mode 100644 src/libwifi/parse/management/common.c create mode 100644 src/libwifi/parse/management/common.h create mode 100644 src/libwifi/parse/management/deauthentication.c create mode 100644 src/libwifi/parse/management/deauthentication.h create mode 100644 src/libwifi/parse/management/disassociation.c create mode 100644 src/libwifi/parse/management/disassociation.h create mode 100644 src/libwifi/parse/management/probe_request.c create mode 100644 src/libwifi/parse/management/probe_request.h create mode 100644 src/libwifi/parse/management/probe_response.c create mode 100644 src/libwifi/parse/management/probe_response.h create mode 100644 src/libwifi/parse/management/reassoc_request.c create mode 100644 src/libwifi/parse/management/reassoc_request.h create mode 100644 src/libwifi/parse/management/reassoc_response.c create mode 100644 src/libwifi/parse/management/reassoc_response.h create mode 100644 src/libwifi/parse/misc/radiotap.c create mode 100644 src/libwifi/parse/misc/radiotap.h create mode 100644 src/libwifi/parse/misc/security.c create mode 100644 src/libwifi/parse/misc/security.h (limited to 'src') 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 @@ +#ifndef LIBWIFI_H +#define LIBWIFI_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "libwifi/core/core.h" +#include "libwifi/core/frame/control/cts.h" +#include "libwifi/core/frame/control/rts.h" +#include "libwifi/core/frame/crc.h" +#include "libwifi/core/frame/data/data.h" +#include "libwifi/core/frame/frame.h" +#include "libwifi/core/frame/management/action.h" +#include "libwifi/core/frame/management/assoc_request.h" +#include "libwifi/core/frame/management/assoc_response.h" +#include "libwifi/core/frame/management/atim.h" +#include "libwifi/core/frame/management/authentication.h" +#include "libwifi/core/frame/management/beacon.h" +#include "libwifi/core/frame/management/common.h" +#include "libwifi/core/frame/management/deauthentication.h" +#include "libwifi/core/frame/management/disassociation.h" +#include "libwifi/core/frame/management/probe_request.h" +#include "libwifi/core/frame/management/probe_response.h" +#include "libwifi/core/frame/management/reassoc_request.h" +#include "libwifi/core/frame/management/reassoc_response.h" +#include "libwifi/core/frame/management/timing_ad.h" +#include "libwifi/core/frame/tag.h" +#include "libwifi/core/frame/tag_iterator.h" +#include "libwifi/core/misc/byteswap.h" +#include "libwifi/core/misc/epoch.h" +#include "libwifi/core/misc/llc.h" +#include "libwifi/core/misc/radiotap.h" +#include "libwifi/core/misc/security.h" +#include "libwifi/core/misc/types.h" +#include "libwifi/core/radiotap/platform.h" +#include "libwifi/core/radiotap/radiotap.h" +#include "libwifi/core/radiotap/radiotap_iter.h" +#include "libwifi/gen/control/cts.h" +#include "libwifi/gen/control/rts.h" +#include "libwifi/gen/management/action.h" +#include "libwifi/gen/management/assoc_request.h" +#include "libwifi/gen/management/assoc_response.h" +#include "libwifi/gen/management/atim.h" +#include "libwifi/gen/management/authentication.h" +#include "libwifi/gen/management/beacon.h" +#include "libwifi/gen/management/common.h" +#include "libwifi/gen/management/deauthentication.h" +#include "libwifi/gen/management/disassociation.h" +#include "libwifi/gen/management/probe_request.h" +#include "libwifi/gen/management/probe_response.h" +#include "libwifi/gen/management/reassoc_request.h" +#include "libwifi/gen/management/reassoc_response.h" +#include "libwifi/gen/management/timing_ad.h" +#include "libwifi/gen/misc/radiotap.h" +#include "libwifi/parse/data/data.h" +#include "libwifi/parse/data/eapol.h" +#include "libwifi/parse/management/assoc_request.h" +#include "libwifi/parse/management/assoc_response.h" +#include "libwifi/parse/management/beacon.h" +#include "libwifi/parse/management/common.h" +#include "libwifi/parse/management/deauthentication.h" +#include "libwifi/parse/management/disassociation.h" +#include "libwifi/parse/management/probe_request.h" +#include "libwifi/parse/management/probe_response.h" +#include "libwifi/parse/management/reassoc_request.h" +#include "libwifi/parse/management/reassoc_response.h" +#include "libwifi/parse/misc/radiotap.h" +#include "libwifi/parse/misc/security.h" + +#ifdef __cplusplus +} +#endif + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "core.h" +#include +#include +#include + +/** + * Random MAC addresses, achieved by obtaining 6 bytes of /dev/urandom via getrandom() + */ +void libwifi_random_mac(unsigned char buf[6], unsigned char prefix[3]) { + memset(buf, 0, 6); + if (prefix != NULL) { + memcpy(buf, prefix, 3); + getrandom(buf + 3, 3, 0); + } else { + getrandom(buf, 6, 0); + } +} + +/** + * Dummy linker test function + */ +void libwifi_dummy(void) { + return; +} + +/** + * Version + */ +const char *libwifi_get_version(void) { + return LIBWIFI_VERSION; +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_H +#define LIBWIFI_CORE_H + +#define LIBWIFI_VERSION "0.0.1" + +/** + * Commonly used fixed fields + */ +#define LIBWIFI_BCAST_MAC "\xFF\xFF\xFF\xFF\xFF\xFF" +#define LIBWIFI_ZERO_MAC "\x00\x00\x00\x00\x00\x00" + +/** + * Helpers for MAC Addresses + */ +#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] +#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x" + +/** + * Function to randomly generate a MAC address. + * + * @param buf A buffer for the generated MAC to be written to + * @param prefix An optional OUI prefix + */ +void libwifi_random_mac(unsigned char buf[6], unsigned char prefix[3]); + +/** + * Dummy function for linker testing purposes. + */ +void libwifi_dummy(void); + +/** + * Obtain the version of libwifi. + * + * @return The version of the installed libwifi. + */ +const char *libwifi_get_version(void); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_CTS_H +#define LIBWIFI_CORE_CTS_H + +#include "../frame.h" + +/** + * Clear-to-Send Layout + * ─────────────────────────────────── + * ┌─────────────────────────────────┐ + * │ Header │ Bytes: 4 + * ├─────────────────────────────────┤ + * │ Receiver Address │ Bytes: 6 + * └─────────────────────────────────┘ + */ +struct libwifi_cts { + struct libwifi_ctrl_frame_header frame_header; + unsigned char receiver_addr[6]; +}; + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_RTS_H +#define LIBWIFI_CORE_RTS_H + +#include "../frame.h" + +/** + * Request-to-Send Layout + * ─────────────────────────────────── + * ┌─────────────────────────────────┐ + * │ Header │ Bytes: 4 + * ├─────────────────────────────────┤ + * │ Receiver Address │ Bytes: 6 + * ├─────────────────────────────────┤ + * │ Transmitter Address │ Bytes: 4 + * └─────────────────────────────────┘ + */ +struct libwifi_rts { + struct libwifi_ctrl_frame_header frame_header; + unsigned char receiver_addr[6]; + unsigned char transmitter_addr[6]; +}; + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "crc.h" +#include "../misc/byteswap.h" + +#include +#include + +/* + * Basic CRC32 implementation for getting the frame check sum of + * a supplied message, usually frame data. + */ +uint32_t libwifi_crc32(const unsigned char *message, int message_len) { + int i, j; + unsigned int byte, crc, mask; + i = 0; + crc = 0xFFFFFFFF; + while (i < message_len) { + byte = message[i]; + crc = crc ^ byte; + for (j = 7; j >= 0; j--) { + mask = -(crc & 1); + crc = (crc >> 1) ^ (0xEDB88320 & mask); + } + i = i + 1; + } + return ~crc; +} + +/* + * Specific function for calculating a frame FCS, byteswapped for the + * host endianess. + */ +uint32_t libwifi_calculate_fcs(const unsigned char *frame, size_t frame_len) { + return BYTESWAP32(libwifi_crc32(frame, frame_len)); +} + +/* + * Verify a frame containing a FCS at the end to the FCS calculated + * by libwifi. + */ +int libwifi_frame_verify(void *frame, size_t frame_len) { + uint32_t oCRC = *((uint32_t *) ((char *) frame + frame_len)); + uint32_t rCRC = libwifi_calculate_fcs(frame, frame_len); + + if (rCRC == oCRC) { + return 1; + } + return 0; +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_CRC_H +#define LIBWIFI_CORE_CRC_H + +#include +#include + +/** + * Calculate the CRC32 sum of a given buffer. + * + * @param message Buffer of data + * @param message_len Length of the data buffer + * @return CRC32 sum of the given buffer + */ +uint32_t libwifi_crc32(const unsigned char *message, int message_len); + +/** + * Calculate the frame checksum for an 802.11 frame. + * + * @param frame An 802.11 frame + * @param frame_len Length of the frame + * @return frame checksum of the frame + */ +uint32_t libwifi_calculate_fcs(const unsigned char *frame, size_t frame_len); + +/** + * Check if the given 802.11 frame has a valid FCS. + * + * @param frame An 802.11 frame with an FCS + * @param frame_len Length of the frame + * @return 1 if verified, 0 if not + */ +int libwifi_frame_verify(void *frame, size_t frame_len); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_DATA_H +#define LIBWIFI_CORE_DATA_H + +#include + +/** + * Data Frame Layout + * ─────────────────────────────────── + */ +struct libwifi_data { + unsigned char transmitter[6]; + unsigned char receiver[6]; + unsigned char *body; + size_t body_len; +}; + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "frame.h" +#include "../../parse/misc/radiotap.h" +#include "../misc/byteswap.h" +#include "../radiotap/radiotap.h" + +#include +#include +#include + +/* + * Turn sniffed data into a libwifi_frame struct for use with other libwifi functions. + * + * Supported frames: + * - Management Frames (Ordered) + * - Management Frames (Unordered) + * - Data Frames + * - QoS Data Frames + * - Control Frames + */ +int libwifi_get_wifi_frame(struct libwifi_frame *fi, const unsigned char *frame, size_t frame_len, + int radiotap) { + union libwifi_frame_header fh = {0}; + size_t header_len = 0; + size_t frame_data_len = frame_len; + unsigned char *frame_data = malloc(frame_data_len); + memcpy(frame_data, (unsigned char *) frame, frame_data_len); + + if (radiotap) { + struct libwifi_radiotap_info rtap_info = {0}; + libwifi_parse_radiotap_info(&rtap_info, frame_data); + + // Skip forward by the length of the radiotap header + frame_data_len -= rtap_info.length; + unsigned char *new_data = malloc(frame_data_len); + memcpy(new_data, frame_data + rtap_info.length, frame_data_len); + free(frame_data); + frame_data = new_data; + + // Remove the FCS from the end of the frame data, if present + if (rtap_info.flags & IEEE80211_RADIOTAP_F_FCS) { + fi->flags |= LIBWIFI_FLAGS_FCS_PRESENT; + frame_data_len -= sizeof(uint32_t); // FCS is 4 bytes wide + frame_data = realloc(frame_data, frame_data_len); + if (frame_data == NULL) { + return -ENOMEM; + } + } + } + + struct libwifi_frame_ctrl *frame_control = (struct libwifi_frame_ctrl *) frame_data; + + switch (frame_control->type) { + case TYPE_DATA: + switch (frame_control->subtype) { + case SUBTYPE_DATA_QOS_DATA: + case SUBTYPE_DATA_QOS_NULL: + case SUBTYPE_DATA_QOS_DATA_CF_ACK: + case SUBTYPE_DATA_QOS_DATA_CF_ACK_CF_POLL: + case SUBTYPE_DATA_QOS_DATA_CF_POLL: + case SUBTYPE_DATA_QOS_CF_ACK_CF_POLL: + case SUBTYPE_DATA_QOS_CF_POLL: + fi->flags |= LIBWIFI_FLAGS_IS_QOS; + break; + } + + if (fi->flags & LIBWIFI_FLAGS_IS_QOS) { + header_len = sizeof(struct libwifi_data_qos_frame_header); + } else { + header_len = sizeof(struct libwifi_data_frame_header); + } + + if (frame_data_len < header_len) { + free(frame_data); + return -EINVAL; + } + + if (fi->flags & LIBWIFI_FLAGS_IS_QOS) { + memset(&fh.data_qos, 0, sizeof(struct libwifi_data_qos_frame_header)); + memcpy(&fh.data_qos, frame_data, sizeof(struct libwifi_data_qos_frame_header)); + } else { + memset(&fh.data, 0, sizeof(struct libwifi_data_frame_header)); + memcpy(&fh.data, frame_data, sizeof(struct libwifi_data_frame_header)); + } + break; + case TYPE_MANAGEMENT: + if (frame_control->flags.ordered) { + header_len = sizeof(struct libwifi_mgmt_ordered_frame_header); + if (frame_data_len < header_len) { + free(frame_data); + return -EINVAL; + } + memcpy(&fh.mgmt_ordered, frame_data, header_len); + } else { + header_len = sizeof(struct libwifi_mgmt_unordered_frame_header); + if (frame_data_len < header_len) { + free(frame_data); + return -EINVAL; + } + memcpy(&fh.mgmt_unordered, frame_data, header_len); + } + break; + case TYPE_CONTROL: + header_len = sizeof(struct libwifi_ctrl_frame_header); + if (frame_data_len < header_len) { + free(frame_data); + return -EINVAL; + } + memcpy(&fh.ctrl, frame_data, sizeof(struct libwifi_ctrl_frame_header)); + break; + default: + free(frame_data); + return -EINVAL; + } + + fi->len = frame_data_len; + fi->header = fh; + fi->header_len = header_len; + memcpy(&fi->frame_control, frame_control, sizeof(struct libwifi_frame_ctrl)); + + fi->body = malloc(fi->len - fi->header_len); + memcpy(fi->body, frame_data + header_len, (fi->len - fi->header_len)); + + free(frame_data); + + return 0; +} + +void libwifi_free_wifi_frame(struct libwifi_frame *fi) { + free(fi->body); +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_FRAME_H +#define LIBWIFI_CORE_FRAME_H + +#include "../../core/misc/byteswap.h" + +#include +#include + +/* libwifi_frame Flags */ +#define LIBWIFI_FLAGS_FCS_PRESENT (1 << 0) +#define LIBWIFI_FLAGS_IS_QOS (1 << 1) + +/* Defined frame types and sub-types */ +enum libwifi_frame_type { + TYPE_MANAGEMENT = 0, + TYPE_CONTROL = 1, + TYPE_DATA = 2, + TYPE_EXTENSION = 3, +}; +enum libwifi_mgmt_subtypes { + SUBTYPE_ASSOC_REQ = 0, + SUBTYPE_ASSOC_RESP = 1, + SUBTYPE_REASSOC_REQ = 2, + SUBTYPE_REASSOC_RESP = 3, + SUBTYPE_PROBE_REQ = 4, + SUBTYPE_PROBE_RESP = 5, + SUBTYPE_TIME_ADV = 6, + // Reserved = 7, + SUBTYPE_BEACON = 8, + SUBTYPE_ATIM = 9, + SUBTYPE_DISASSOC = 10, + SUBTYPE_AUTH = 11, + SUBTYPE_DEAUTH = 12, + SUBTYPE_ACTION = 13, + SUBTYPE_ACTION_NOACK = 14, + // Reserved = 15, +}; +enum libwifi_control_subtypes { + // Reserved = 0-3, + SUBTYPE_TACK = 3, + SUBTYPE_BEAMFORM_REPORT_POLL = 4, + SUBTYPE_VHT_NDP_ANNOUNCE = 5, + SUBTYPE_CF_EXTENSION = 6, + SUBTYPE_WRAPPER = 7, + SUBTYPE_BLOCK_ACK_REQ = 8, + SUBTYPE_BLOCK_ACK = 9, + SUBTYPE_PS_POLL = 10, + SUBTYPE_RTS = 11, + SUBTYPE_CTS = 12, + SUBTYPE_ACK = 13, + SUBTYPE_CF_END = 14, + SUBTYPE_CF_END_CF_ACK = 15, +}; +enum libwifi_control_extension_subtypes { + // Reserved = 0-1, + SUBTYPE_CF_EXT_POLL = 2, + SUBTYPE_CF_EXT_SPR = 3, + SUBTYPE_CF_EXT_GRANT = 4, + SUBTYPE_CF_EXT_DMG_CTS = 5, + SUBTYPE_CF_EXT_DMG_DTS = 6, + SUBTYPE_CF_EXT_GRANT_ACK = 7, + SUBTYPE_CF_EXT_SSW = 8, + SUBTYPE_CF_EXT_SSW_FEEDBACK = 9, + SUBTYPE_CF_EXT_SSW_ACK = 10, + // Reserved = 11-15, +}; +enum libwifi_data_subtypes { + SUBTYPE_DATA = 0, + // Reserved = 1-3, + SUBTYPE_DATA_NULL = 4, + // Reserved = 4-7, + SUBTYPE_DATA_QOS_DATA = 8, + SUBTYPE_DATA_QOS_DATA_CF_ACK = 9, + SUBTYPE_DATA_QOS_DATA_CF_POLL = 10, + SUBTYPE_DATA_QOS_DATA_CF_ACK_CF_POLL = 11, + SUBTYPE_DATA_QOS_NULL = 12, + // Reserved = 13, + SUBTYPE_DATA_QOS_CF_POLL = 14, + SUBTYPE_DATA_QOS_CF_ACK_CF_POLL = 15, +}; +enum libwifi_extension_subtypes { + SUBTYPE_EXTENSION_DMG_BEACON = 0, + SUBTYPE_EXTENSION_SIG_BEACON = 1, + // Reserved = 2-15 +}; + +/* + * libwifi Representation of an 802.11 Frame Control Field's Flags. + */ + +struct libwifi_frame_ctrl_flags { + unsigned int to_ds : 1; + unsigned int from_ds : 1; + unsigned int more_frags : 1; + unsigned int retry : 1; + unsigned int power_mgmt : 1; + unsigned int more_data : 1; + unsigned int protect : 1; + unsigned int ordered : 1; +} __attribute__((packed)); + +/* + * libwifi Representation of an 802.11 Frame Control Field. + */ +struct libwifi_frame_ctrl { + unsigned int version : 2; + unsigned int type : 2; + unsigned int subtype : 4; + struct libwifi_frame_ctrl_flags flags; +} __attribute__((packed)); + +/* + * libwifi Representation of an 802.11 Sequence Control Field. + */ +struct libwifi_seq_control { + unsigned int fragment_number : 4; + unsigned int sequence_number : 12; +} __attribute__((packed)); + +/* + * libwifi Representation of an 802.11 Data QoS Control Field. + * + * As the bits of the QoS Control Field can vary depending on other + * factors, generic bit names are used here. + */ +struct libwifi_qos_control { + unsigned int bit1 : 1; + unsigned int bit2 : 1; + unsigned int bit3 : 1; + unsigned int bit4 : 1; + unsigned int bit5 : 1; + unsigned int bit6 : 1; + unsigned int bit7 : 1; + unsigned int bit8 : 1; + unsigned int bit9 : 1; + unsigned int bit10 : 1; + unsigned int bit11 : 1; + unsigned int bit12 : 1; + unsigned int bit13 : 1; + unsigned int bit14 : 1; + unsigned int bit15 : 1; + unsigned int bit16 : 1; +} __attribute__((packed)); + +/* + * libwifi Representation of an ordered Management Frame header. + * + * ┌───────────────────────────┐ + * │ Frame Control Field │ ── 2 Bytes + * ├───────────────────────────┤ + * │ Duration │ ── 2 Bytes + * ├───────────────────────────┤ + * │ Address 1 │ ── 6 Bytes + * ├───────────────────────────┤ + * │ Address 2 │ ── 6 Bytes + * ├───────────────────────────┤ + * │ Address 3 │ ── 6 Bytes + * ├───────────────────────────┤ + * │ Sequence Control │ ── 2 Bytes + * ├───────────────────────────┤ + * │ HT Control │ ── 4 Bytes + * └───────────────────────────┘ + */ +struct libwifi_mgmt_ordered_frame_header { + struct libwifi_frame_ctrl frame_control; + uint16_t duration; + unsigned char addr1[6]; + unsigned char addr2[6]; + unsigned char addr3[6]; + struct libwifi_seq_control seq_control; + uint32_t ht_control; +} __attribute__((packed)); + +/* + * libwifi Representation of an unordered Management Frame header. + * + * ┌───────────────────────────┐ + * │ Frame Control Field │ ── 2 Bytes + * ├───────────────────────────┤ + * │ Duration │ ── 2 Bytes + * ├───────────────────────────┤ + * │ Address 1 │ ── 6 Bytes + * ├───────────────────────────┤ + * │ Address 2 │ ── 6 Bytes + * ├───────────────────────────┤ + * │ Address 3 │ ── 6 Bytes + * ├───────────────────────────┤ + * │ Sequence Control │ ── 2 Bytes + * └───────────────────────────┘ + */ +struct libwifi_mgmt_unordered_frame_header { + struct libwifi_frame_ctrl frame_control; + uint16_t duration; + unsigned char addr1[6]; + unsigned char addr2[6]; + unsigned char addr3[6]; + struct libwifi_seq_control seq_control; +} __attribute__((packed)); + +/* + * libwifi Representation of a Control Frame header. + * + * ┌───────────────────────────┐ + * │ Frame Control Field │ ── 2 Bytes + * ├───────────────────────────┤ + * │ Duration │ ── 2 Bytes + * └───────────────────────────┘ + */ +struct libwifi_ctrl_frame_header { + struct libwifi_frame_ctrl frame_control; + uint16_t duration; +} __attribute__((packed)); + +/* + * libwifi Representation of a non-QoS Data Frame header. + * + * ┌───────────────────────────┐ + * │ Frame Control Field │ ── 2 Bytes + * ├───────────────────────────┤ + * │ Duration │ ── 2 Bytes + * ├───────────────────────────┤ + * │ Address 1 │ ── 6 Bytes + * ├───────────────────────────┤ + * │ Address 2 │ ── 6 Bytes + * ├───────────────────────────┤ + * │ Address 3 │ ── 6 Bytes + * ├───────────────────────────┤ + * │ Sequence Control │ ── 2 Bytes + * └───────────────────────────┘ + */ +struct libwifi_data_frame_header { + struct libwifi_frame_ctrl frame_control; + uint16_t duration; + unsigned char addr1[6]; + unsigned char addr2[6]; + unsigned char addr3[6]; + struct libwifi_seq_control seq_control; +} __attribute__((packed)); + +/* + * libwifi Representation of a QoS Data Frame header. + * + * ┌───────────────────────────┐ + * │ Frame Control Field │ ── 2 Bytes + * ├───────────────────────────┤ + * │ Duration │ ── 2 Bytes + * ├───────────────────────────┤ + * │ Address 1 │ ── 6 Bytes + * ├───────────────────────────┤ + * │ Address 2 │ ── 6 Bytes + * ├───────────────────────────┤ + * │ Address 3 │ ── 6 Bytes + * ├───────────────────────────┤ + * │ Sequence Control │ ── 2 Bytes + * ├───────────────────────────┤ + * │ QoS Control │ ── 2 Bytes + * └───────────────────────────┘ + */ +struct libwifi_data_qos_frame_header { + struct libwifi_frame_ctrl frame_control; + uint16_t duration; + unsigned char addr1[6]; + unsigned char addr2[6]; + unsigned char addr3[6]; + struct libwifi_seq_control seq_control; + struct libwifi_qos_control qos_control; +} __attribute__((packed)); + +/* + * Union of all frame type headers for use with a libwifi_frame struct + */ +union libwifi_frame_header { + struct libwifi_mgmt_ordered_frame_header mgmt_ordered; + struct libwifi_mgmt_unordered_frame_header mgmt_unordered; + struct libwifi_ctrl_frame_header ctrl; + struct libwifi_data_frame_header data; + struct libwifi_data_qos_frame_header data_qos; +}; + +/* + * Union of all Management Frame headers + */ +union libwifi_mgmt_frame_header { + struct libwifi_mgmt_ordered_frame_header ordered; + struct libwifi_mgmt_unordered_frame_header unordered; +}; + +/* + * A libwifi_frame struct is used to represent any type of 802.11 + * frame in libwifi. + */ +struct libwifi_frame { + uint16_t flags; + struct libwifi_frame_ctrl frame_control; + size_t len; + union libwifi_frame_header header; + size_t header_len; + unsigned char *body; +}; + +/** + * Convert a sniffed 802.11 frame into a libwifi_frame. + * + * @param fi A libwifi_frame struct + * @param frame An 802.11 frame + * @param frame_len Length of the sniffed 802.11 frame + * @return + */ +int libwifi_get_wifi_frame(struct libwifi_frame *fi, const unsigned char *frame, size_t frame_len, + int radiotap); + +/** + * Free any dynamically allocated data inside a libwifi_frame. + * + * @param fi A libwifi_frame struct + */ +void libwifi_free_wifi_frame(struct libwifi_frame *fi); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_ACTIONS_H +#define LIBWIFI_CORE_ACTIONS_H + +#include "../frame.h" +#include + +/* Defined action fixed parameter values */ +enum libwifi_actions { + ACTION_SPECTRUM_MGMT = 0, + ACTION_QOS = 1, + // Reserved 2 + ACTION_BLOCK_ACK = 3, + ACTION_PUBLIC = 4, + ACTION_RADIO_MEASUREMENT = 5, + ACTION_FAST_BSS_TRANSITION = 6, + ACTION_HT = 7, + ACTION_SA_QUERY = 8, + ACTION_PROTECTED_DOPA = 9, + ACTION_WNM = 10, + ACTION_UNSUPPORTED_WNM = 11, + ACTION_TDLS = 12, + ACTION_MESH = 13, + ACTION_MULTIHOP = 14, + ACTION_SELF_PROTECTED = 15, + ACTION_DMG = 16, + // Reserved 17 + ACTION_FAST_SESSION_TRANSFER = 18, + ACTION_ROBUST_AV_STREAM = 19, + ACTION_UNPROTECTED_DMG = 20, + ACTION_VHT = 21, + ACTION_UNPROTECTED_SIG = 22, + ACTION_SIG = 23, + ACTION_FLOW_CONTROL = 24, + ACTION_CTRL_MCS_NEG = 25, + ACTION_FILS = 26, + ACTION_CDMG = 27, + ACTION_CMMG = 28, + ACTION_GLK = 29, + // Reserved 30-125 + ACTION_VENDOR_PROTECTED = 126, + ACTION_VENDOR = 127, + // Error 128-255 +}; + +/** + * Action Layout + * ───────────────────────────────────── + * ┌─────────────────────────────────────┐ + * │ Header │ Bytes: 24 + * ├─────────────────────────────────────┤ + * │ Fixed Parameters │ Bytes: Variable + * │┌───────────────────────────────────┐│ + * ││ category ││ Bytes: 1 + * │├───────────────────────────────────┤│ + * ││ detail ││ Bytes: Variable + * ││┌─────────────────────────────────┐││ + * │││ tagged parameters │││ + * ││└─────────────────────────────────┘││ + * │└───────────────────────────────────┘│ + * └─────────────────────────────────────┘ + */ + +struct libwifi_action_detail { + uint8_t detail_length; + char *detail; +} __attribute__((packed)); + +struct libwifi_action_fixed_parameters { + uint8_t category; + struct libwifi_action_detail details; +} __attribute__((packed)); + +struct libwifi_action { + struct libwifi_mgmt_unordered_frame_header frame_header; + struct libwifi_action_fixed_parameters fixed_parameters; +} __attribute__((packed)); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_ASSOCREQ_H +#define LIBWIFI_CORE_ASSOCREQ_H + +#include "../frame.h" +#include "../tag.h" +#include + +/** + * Association Request Layout + * ───────────────────────────────── + * ┌─────────────────────────────────┐ + * │ Header │ Bytes: 24 + * ├─────────────────────────────────┤ + * │ Fixed Parameters │ Bytes: 4 + * │┌───────────────────────────────┐│ + * ││ capabilities ││ Bytes: 2 + * │├───────────────────────────────┤│ + * ││ listen interval ││ Bytes: 2 + * │└───────────────────────────────┘│ + * ├─────────────────────────────────┤ + * │ Tagged Parameters │ Bytes: Variable + * └─────────────────────────────────┘ + */ + +struct libwifi_assoc_req_fixed_parameters { + uint16_t capabilities_information; + uint16_t listen_interval; +} __attribute__((packed)); + +struct libwifi_assoc_req { + struct libwifi_mgmt_unordered_frame_header frame_header; + struct libwifi_assoc_req_fixed_parameters fixed_parameters; + struct libwifi_tagged_parameters tags; +} __attribute__((packed)); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_ASSOCRESP_H +#define LIBWIFI_CORE_ASSOCRESP_H + +#include "../frame.h" +#include "../tag.h" +#include + +/** + * Association Response Layout + * ───────────────────────────────── + * ┌─────────────────────────────────┐ + * │ Header │ Bytes: 24 + * ├─────────────────────────────────┤ + * │ Fixed Parameters │ Bytes: 6 + * │┌───────────────────────────────┐│ + * ││ capabilities ││ Bytes: 2 + * │├───────────────────────────────┤│ + * ││ status ││ Bytes: 2 + * │├───────────────────────────────┤│ + * ││ association id ││ Bytes: 2 + * │└───────────────────────────────┘│ + * ├─────────────────────────────────┤ + * │ Tagged Parameters │ Bytes: Variable + * └─────────────────────────────────┘ + */ + +struct libwifi_assoc_resp_fixed_parameters { + uint16_t capabilities_information; + uint16_t status_code; + uint16_t association_id; +} __attribute__((packed)); + +struct libwifi_assoc_resp { + struct libwifi_mgmt_unordered_frame_header frame_header; + struct libwifi_assoc_resp_fixed_parameters fixed_parameters; + struct libwifi_tagged_parameters tags; +} __attribute__((packed)); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_ATIM_H +#define LIBWIFI_CORE_ATIM_H + +#include "../frame.h" + +/** + * ATIM Frame Layout + * ───────────────────────────────── + * ┌─────────────────────────────────┐ + * │ Header │ Bytes: 24 + * └─────────────────────────────────┘ + */ + +struct libwifi_atim { + struct libwifi_mgmt_unordered_frame_header frame_header; +}; + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_AUTH_H +#define LIBWIFI_CORE_AUTH_H + +#include "../frame.h" +#include "../tag.h" +#include + +/** + * Authentication Layout + * ───────────────────────────────── + * ┌─────────────────────────────────┐ + * │ Header │ Bytes: 24 + * ├─────────────────────────────────┤ + * │ Fixed Parameters │ Bytes: 6 + * │┌───────────────────────────────┐│ + * ││ algorithm ││ Bytes: 2 + * │├───────────────────────────────┤│ + * ││ transaction ││ Bytes: 2 + * │├───────────────────────────────┤│ + * ││ status ││ Bytes: 2 + * │└───────────────────────────────┘│ + * ├─────────────────────────────────┤ + * │ Tagged Parameters │ Bytes: Variable + * └─────────────────────────────────┘ + */ + +struct libwifi_auth_fixed_parameters { + uint16_t algorithm_number; + uint16_t transaction_sequence; + uint16_t status_code; +} __attribute__((packed)); + +struct libwifi_auth { + struct libwifi_mgmt_unordered_frame_header frame_header; + struct libwifi_auth_fixed_parameters fixed_parameters; + struct libwifi_tagged_parameters tags; +} __attribute__((packed)); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_BEACON_H +#define LIBWIFI_CORE_BEACON_H + +#include "../frame.h" +#include "../tag.h" +#include + +/** + * Beacon Layout + * ────────────────────────────── + * ┌──────────────────────────────┐ + * │ Header │ Bytes: 24 + * ├──────────────────────────────┤ + * │ Fixed Parameters │ Bytes: 12 + * │┌────────────────────────────┐│ + * ││ timestamp ││ Bytes: 4 + * │├────────────────────────────┤│ + * ││ interval ││ Bytes: 2 + * │├────────────────────────────┤│ + * ││ capabilities ││ Bytes: 2 + * │└────────────────────────────┘│ + * ├──────────────────────────────┤ + * │ Tagged Parameters │ Bytes: Variable + * └──────────────────────────────┘ + */ + +struct libwifi_beacon_fixed_parameters { + uint64_t timestamp; + uint16_t beacon_interval; + uint16_t capabilities_information; +} __attribute__((packed)); + +struct libwifi_beacon { + struct libwifi_mgmt_unordered_frame_header frame_header; + struct libwifi_beacon_fixed_parameters fixed_parameters; + struct libwifi_tagged_parameters tags; +} __attribute__((packed)); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_COMMON_H +#define LIBWIFI_CORE_COMMON_H + +#include "../../misc/security.h" +#include "../tag.h" +#include +#include + +#define LIBWIFI_BSS 0 +#define LIBWIFI_STA 1 + +/* + * A libwifi_bss struct is used as a common model for BSS / APs, and can be derived + * from parsed frames or used to generate new frames. Fields may be optional. + * + * transmitter - The transmitter MAC address + * receiver - The receiver MAC address + * bssid - BSSID MAC address + * ssid - AP SSID + * hidden - Hidden state boolean + * channel - BSS Channel + * wps - WPS state boolean + * encryption_info - Bitfield of encryption state, such as WPA version and ciphers + * signal - RSSI in dBm + * wpa_info - WPA1 information, present if encryption_info has the WPA1 bit set + * rsn_info - WPA2 and/or WPA3 information, present if encryption_info has WPA2 or WPA3 bit set + * tags - List of tagged parameters + */ +struct libwifi_bss { + unsigned char transmitter[6]; + unsigned char receiver[6]; + unsigned char bssid[6]; + char ssid[33]; + int8_t hidden; + uint8_t channel; + uint8_t wps; + uint64_t encryption_info; + int signal; + struct libwifi_wpa_info wpa_info; + struct libwifi_rsn_info rsn_info; + struct libwifi_tagged_parameters tags; +}; + +/* + * A libwifi_bss can be populated with dynamically allocated tags, which must be free'd by + * the user application to avoid memory leaks. This function provides an easy wrapper for any + * libwifi allocations made. + */ +static inline void libwifi_free_bss(struct libwifi_bss *bss) { + free(bss->tags.parameters); +} + +/* + * A libwifi_sta struct is used as a common model for stations, roaming or associated, + * and can be derived from parsed frames or used to generate new frames. Fields may be optional. + * + * channel - BSS Channel + * randomized - Client has a likely randomized MAC + * transmitter - The transmitter MAC address + * receiver - The receiver MAC address + * bssid - BSSID MAC address + * ssid - AP SSID + * broadcast_ssid - STA is broadcasting for SSID + * tags - List of tagged parameters + */ +struct libwifi_sta { + uint8_t channel; + uint8_t randomized; + unsigned char transmitter[6]; + unsigned char receiver[6]; + unsigned char bssid[6]; + char ssid[33]; + uint8_t broadcast_ssid; + struct libwifi_tagged_parameters tags; +}; + +/* + * A libwifi_sta can be populated with dynamically allocated tags, which must be free'd by + * the user application to avoid memory leaks. This function provides an easy wrapper for any + * libwifi allocations made. + */ +static inline void libwifi_free_sta(struct libwifi_sta *sta) { + free(sta->tags.parameters); +} + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_DEAUTH_H +#define LIBWIFI_CORE_DEAUTH_H + +#include "../frame.h" +#include "../tag.h" +#include + +/** + * Deauthentication Layout + * ────────────────────────── + * ┌──────────────────────────┐ + * │ Header │ Bytes: 24 + * ├──────────────────────────┤ + * │ Fixed Parameters │ Bytes: 2 + * │┌────────────────────────┐│ + * ││ reason code ││ Bytes: 2 + * │└────────────────────────┘│ + * ├──────────────────────────┤ + * │ Tagged Parameters │ Bytes: Variable + * └──────────────────────────┘ + */ + +struct libwifi_deauth_fixed_parameters { + uint16_t reason_code; +} __attribute__((packed)); + +struct libwifi_deauth { + struct libwifi_mgmt_unordered_frame_header frame_header; + struct libwifi_deauth_fixed_parameters fixed_parameters; + struct libwifi_tagged_parameters tags; +} __attribute__((packed)); + +struct libwifi_parsed_deauth { + int ordered; + union libwifi_mgmt_frame_header frame_header; + struct libwifi_deauth_fixed_parameters fixed_parameters; + struct libwifi_tagged_parameters tags; +} __attribute__((packed)); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_DISASSOC_H +#define LIBWIFI_CORE_DISASSOC_H + +#include "../frame.h" +#include "../tag.h" +#include + +/** + * Disassociation Layout + * ────────────────────────── + * ┌──────────────────────────┐ + * │ Header │ Bytes: 24 + * ├──────────────────────────┤ + * │ Fixed Parameters │ Bytes: 2 + * │┌────────────────────────┐│ + * ││ reason code ││ Bytes: 2 + * │└────────────────────────┘│ + * ├──────────────────────────┤ + * │ Tagged Parameters │ Bytes: Variable + * └──────────────────────────┘ + */ + +struct libwifi_disassoc_fixed_parameters { + uint16_t reason_code; +} __attribute__((packed)); + +struct libwifi_disassoc { + struct libwifi_mgmt_unordered_frame_header frame_header; + struct libwifi_disassoc_fixed_parameters fixed_parameters; + struct libwifi_tagged_parameters tags; +} __attribute__((packed)); + +struct libwifi_parsed_disassoc { + int ordered; + union libwifi_mgmt_frame_header frame_header; + struct libwifi_disassoc_fixed_parameters fixed_parameters; + struct libwifi_tagged_parameters tags; +} __attribute__((packed)); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_PROBEREQ_H +#define LIBWIFI_CORE_PROBEREQ_H + +#include "../frame.h" +#include "../tag.h" +#include + +/** + * Probe Request Layout + * ────────────────────────── + * ┌──────────────────────────┐ + * │ Header │ Bytes: 24 + * ├──────────────────────────┤ + * │ Tagged Parameters │ Bytes: Variable + * └──────────────────────────┘ + */ + +struct libwifi_probe_req { + struct libwifi_mgmt_unordered_frame_header frame_header; + struct libwifi_tagged_parameters tags; +} __attribute__((packed)); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_PROBERESP_H +#define LIBWIFI_CORE_PROBERESP_H + +#include "../frame.h" +#include "../tag.h" +#include + +/** + * Probe Response Layout + * ────────────────────────────── + * ┌──────────────────────────────┐ + * │ Header │ Bytes: 24 + * ├──────────────────────────────┤ + * │ Fixed Parameters │ Bytes: 12 + * │┌────────────────────────────┐│ + * ││ timestamp ││ Bytes: 4 + * │├────────────────────────────┤│ + * ││ interval ││ Bytes: 2 + * │├────────────────────────────┤│ + * ││ capabilities ││ Bytes: 2 + * │└────────────────────────────┘│ + * ├──────────────────────────────┤ + * │ Tagged Parameters │ Bytes: Variable + * └──────────────────────────────┘ + */ + +struct libwifi_probe_resp_fixed_parameters { + uint64_t timestamp; + uint16_t probe_resp_interval; + uint16_t capabilities_information; +} __attribute__((packed)); + +struct libwifi_probe_resp { + struct libwifi_mgmt_unordered_frame_header frame_header; + struct libwifi_probe_resp_fixed_parameters fixed_parameters; + struct libwifi_tagged_parameters tags; +} __attribute__((packed)); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_REASSOCREQ_H +#define LIBWIFI_CORE_REASSOCREQ_H + +#include "../frame.h" +#include "../tag.h" +#include + +/** + * Reassociation Request Layout + * ─────────────────────────────── + * ┌───────────────────────────────┐ + * │ Header │ Bytes: 24 + * ├───────────────────────────────┤ + * │ Fixed Parameters │ Bytes: 10 + * │┌─────────────────────────────┐│ + * ││ capabilities ││ Bytes: 2 + * │├─────────────────────────────┤│ + * ││ interval ││ Bytes: 2 + * │├─────────────────────────────┤│ + * ││ current AP address ││ Bytes: 6 + * │└─────────────────────────────┘│ + * ├───────────────────────────────┤ + * │ Tagged Parameters │ Bytes: Variable + * └───────────────────────────────┘ + */ + +struct libwifi_reassoc_req_fixed_parameters { + uint16_t capabilities_information; + uint16_t listen_interval; + unsigned char current_ap_address[6]; +} __attribute__((packed)); + +struct libwifi_reassoc_req { + struct libwifi_mgmt_unordered_frame_header frame_header; + struct libwifi_reassoc_req_fixed_parameters fixed_parameters; + struct libwifi_tagged_parameters tags; +} __attribute__((packed)); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_REASSOCRESP_H +#define LIBWIFI_CORE_REASSOCRESP_H + +#include "../frame.h" +#include "../tag.h" +#include + +/** + * Reassociation Response Layout + * ────────────────────────────────── + * ┌──────────────────────────────────┐ + * │ Header │ Bytes: 24 + * ├──────────────────────────────────┤ + * │ Fixed Parameters │ Bytes: 6 + * │┌────────────────────────────────┐│ + * ││ capabilities ││ Bytes: 2 + * │├────────────────────────────────┤│ + * ││ status ││ Bytes: 2 + * │├────────────────────────────────┤│ + * ││ association id ││ Bytes: 2 + * │└────────────────────────────────┘│ + * ├──────────────────────────────────┤ + * │ Tagged Parameters │ Bytes: Variable + * └──────────────────────────────────┘ + */ + +struct libwifi_reassoc_resp_fixed_parameters { + uint16_t capabilities_information; + uint16_t status_code; + uint16_t association_id; +} __attribute__((packed)); + +struct libwifi_reassoc_resp { + struct libwifi_mgmt_unordered_frame_header frame_header; + struct libwifi_reassoc_resp_fixed_parameters fixed_parameters; + struct libwifi_tagged_parameters tags; +} __attribute__((packed)); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_TIMINGAD_H +#define LIBWIFI_CORE_TIMINGAD_H + +#include +#include "../frame.h" +#include "../tag.h" + +/** + * Timing Advertisement Layout + * ────────────────────────────────── + * ┌──────────────────────────────────┐ + * │ Header │ Bytes: 24 + * ├──────────────────────────────────┤ + * │ Fixed Parameters │ Bytes: 6 + * │┌────────────────────────────────┐│ + * ││ timestamp ││ Bytes: 8 + * │├────────────────────────────────┤│ + * ││ measurement pilot interval ││ Bytes: 1 + * │├────────────────────────────────┤│ + * ││ beacon interval ││ Bytes: 2 + * │├────────────────────────────────┤│ + * ││ capabilities information ││ Bytes: 2 + * │├────────────────────────────────┤│ + * ││ country code ││ Bytes: 3 + * │├────────────────────────────────┤│ + * ││ maxmimum regulatory power ││ Bytes: 2 + * │├────────────────────────────────┤│ + * ││ maximum transmit power ││ Bytes: 1 + * │├────────────────────────────────┤│ + * ││ transmit power used ││ Bytes: 1 + * │├────────────────────────────────┤│ + * ││ noise floor ││ Bytes: 1 + * │└────────────────────────────────┘│ + * ├──────────────────────────────────┤ + * │ Tagged Parameters │ Bytes: Variable + * │┌────────────────────────────────┐│ + * ││ timing advert fields ││ Bytes: 17 + * │└────────────────────────────────┘│ + * └──────────────────────────────────┘ + */ + +struct libwifi_timing_advert_fields { + uint8_t timing_capabilities; + unsigned char time_value[10]; + unsigned char time_error[5]; + unsigned char time_update[1]; +} __attribute__((packed)); + +struct libwifi_timing_advert_fixed_params { + uint64_t timestamp; + uint8_t measurement_pilot_interval; + uint16_t beacon_interval; + uint16_t capabilities_information; + char country[3]; + uint16_t max_reg_power; + uint8_t max_tx_power; + uint8_t tx_power_used; + uint8_t noise_floor; +} __attribute__((packed)); + +struct libwifi_timing_advert { + struct libwifi_mgmt_unordered_frame_header frame_header; + struct libwifi_timing_advert_fixed_params fixed_parameters; + struct libwifi_tagged_parameters tags; +} __attribute__((packed)); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tag.h" +#include "tag_iterator.h" + +#include +#include +#include +#include +#include + +int libwifi_add_tag(struct libwifi_tagged_parameters *tags, struct libwifi_tagged_parameter *tag) { + // Calculate the total length of the new tag + size_t parameter_len = sizeof(struct libwifi_tag_header) + tag->header.tag_len; + + // Initalise the supplied tagged parameters list, if not already done. + // Otherwise, extend the allocation to fit the new tag. + if (tags->length == 0) { + tags->parameters = malloc(parameter_len); + if (tags->parameters == NULL) { + return -ENOMEM; + } + } else { + void *buf = realloc(tags->parameters, tags->length + parameter_len); + if (buf == NULL) { + return -ENOMEM; + } + tags->parameters = buf; + } + + // Append the new tag to the list + memcpy(tags->parameters + tags->length, &tag->header, sizeof(struct libwifi_tag_header)); + memcpy(tags->parameters + tags->length + sizeof(struct libwifi_tag_header), tag->body, + tag->header.tag_len); + + // Update total tagged parameters length + tags->length += parameter_len; + + return 0; +} + +int libwifi_remove_tag(struct libwifi_tagged_parameters *tags, int tag_number) { + // Initalise a tag iterator + struct libwifi_tag_iterator it = {0}; + if (libwifi_tag_iterator_init(&it, tags->parameters, tags->length) != 0) { + return -EINVAL; + } + + // Loop through the tagged parameters list until landing on the supplied tag number + do { + if (it.tag_header->tag_num == tag_number) { + // Calculate the length of the tag we're removing, so that we know + // how many bytes to shrink the tagged parameter list by + size_t copy_len = tags->length - + (it.tag_data - tags->parameters) - + (it.tag_header->tag_len + sizeof(struct libwifi_tag_header)); + memcpy(tags->parameters, it.tag_data + it.tag_header->tag_len, copy_len); + size_t new_len = tags->length - it.tag_header->tag_len - sizeof(struct libwifi_tag_header); + tags->parameters = realloc(tags->parameters, new_len); + tags->length = new_len; + break; + } + } while (libwifi_tag_iterator_next(&it) != -1); + + return 0; +} + +size_t libwifi_create_tag(struct libwifi_tagged_parameter *tagged_parameter, int tag_number, + const unsigned char *tag_data, size_t tag_length) { + // Initalise the supplied tagged parameter struct + memset(tagged_parameter, 0, sizeof(struct libwifi_tagged_parameter)); + tagged_parameter->header.tag_len = tag_length; + tagged_parameter->header.tag_num = tag_number; + tagged_parameter->body = malloc(tag_length); + if (tagged_parameter->body == NULL) { + return -ENOMEM; + } + memset(tagged_parameter->body, 0, tag_length); + + // Copy the supplied data into the new tag body + memcpy(tagged_parameter->body, tag_data, tag_length); + + return sizeof(struct libwifi_tag_header) + tag_length; +} + +void libwifi_free_tag(struct libwifi_tagged_parameter *tagged_parameter) { + free(tagged_parameter->body); +} + +size_t libwifi_dump_tag(struct libwifi_tagged_parameter *tag, unsigned char *buf, size_t buf_len) { + if (tag->header.tag_len > buf_len) { + return -EINVAL; + } + + size_t offset = 0; + + memcpy(buf, &tag->header, sizeof(struct libwifi_tag_header)); + offset += sizeof(struct libwifi_tag_header); + memcpy(buf + offset, tag->body, tag->header.tag_len); + offset += tag->header.tag_len; + + return sizeof(struct libwifi_tag_header) + tag->header.tag_len; +} + +int libwifi_quick_add_tag(struct libwifi_tagged_parameters *tags, int tag_number, + const unsigned char *tag_data, size_t tag_length) { + struct libwifi_tagged_parameter tagged_parameter = {0}; + + size_t ret = libwifi_create_tag(&tagged_parameter, tag_number, tag_data, tag_length); + if (ret <= 0) { + return ret; + } + + libwifi_add_tag(tags, &tagged_parameter); + libwifi_free_tag(&tagged_parameter); + + return 0; +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_TAG_H +#define LIBWIFI_CORE_TAG_H + +#include +#include + +/* 802.11 Tagged Parameter values */ +enum libwifi_tag_numbers { + TAG_SSID = 0, + TAG_SUPP_RATES = 1, + // Reserved 2 + TAG_DS_PARAMETER = 3, + TAG_CF_PARAMETER = 4, + TAG_TIM = 5, + TAG_BSS_PARAMETERS = 6, + TAG_COUNTRY = 7, + // Reserved 8-9 + TAG_REQUEST = 10, + TAG_BSS_LOAD = 11, + TAG_EDCA_PARAMETERS = 12, + TAG_TSPEC = 13, + TAG_TCLAS = 14, + TAG_SCHEDULE = 15, + TAG_CHALLENGE_TEXT = 16, + // Reserved 17-31 + TAG_POWER_CONSTRAINT = 32, + TAG_POWER_CAPABILITY = 33, + TAG_TPC_REQUEST = 34, + TAG_TPC_REPORT = 35, + TAG_SUPPORTED_CHANNELS = 36, + TAG_CHANNEL_SWITCH_ANNOUNCEMENT = 37, + TAG_MEASUREMENT_REQUEST = 38, + TAG_MEASUREMENT_REPORT = 39, + TAG_QUIET = 40, + TAG_IBSS_DFS = 41, + TAG_ERP = 42, + TAG_TS_DELAY = 43, + TAG_TCLAS_PROCESSING = 44, + TAG_HT_CAPABILITIES = 45, + TAG_QOS_CAPABILITY = 46, + // Reserved 47 + TAG_RSN = 48, + // Reserved 49 + TAG_EXTENDED_SUPPORTED_RATES = 50, + TAG_AP_CHANNEL_REPORT = 51, + TAG_NEIGHBOR_REPORT = 52, + TAG_RCPI = 53, + TAG_MOBILITY_DOMAIN = 54, + TAG_FAST_BSS_TRANSITION = 55, + TAG_TIMEOUT_INTERVAL = 56, + TAG_RIC_DATA = 57, + TAG_DSE_REGISTERED_LOCATION = 58, + TAG_SUPPORTED_OPERATING_CLASSES = 59, + TAG_EXTENDED_CHANNEL_SWITCH_ANNOUNCEMENT = 60, + TAG_HT_OPERATION = 61, + TAG_SECONDARY_CHANNEL_OFFSET = 62, + TAG_BSS_AVERAGE_ACCESS_DELAY = 63, + TAG_ANTENNA = 64, + TAG_RSNI = 65, + TAG_MEASUREMENT_PILOT_TRANSMISSION = 66, + TAG_BSS_AVAILABLE_ADMISSION_CAPACITY = 67, + TAG_BSS_AC_ACCESS_DELAY = 68, + TAG_TIME_ADVERTISEMENT = 69, + TAG_RM_ENABLED_CAPABILITIES = 70, + TAG_MULTIPLE_BSSID = 71, + TAG_BSS_COEXISTENCE = 72, + TAG_BSS_INTOLERANT_CHANNEL_REPORT = 73, + TAG_OVERLAPPING_BSS_PARAMETERS = 74, + TAG_RIC_DESCRIPTOR = 75, + TAG_MANAGEMENT_MIC = 76, + // Undefined 77 + TAG_EVENT_REQUEST = 78, + TAG_EVENT_REPORT = 79, + TAG_DIAGNOSTIC_REQUEST = 80, + TAG_DIAGNOSTIC_REPORT = 81, + TAG_LOCATION_PARAMTERS = 82, + TAG_NONTRANSMITTED_BSSID_CAPABILITY = 83, + TAG_SSID_LIST = 84, + TAG_MULTIPLE_BSSID_INDEX = 85, + TAG_FMS_DESCRIPTOR = 86, + TAG_FMS_REQUEST = 87, + TAG_FMS_RESPONSE = 88, + TAG_QOS_TRAFFIC_CAPABILITY = 89, + TAG_BSS_MAX_IDLE_PERIOD = 90, + TAG_TFS_REQUEST = 91, + TAG_TFS_RESPONSE = 92, + TAG_WNM_SLEEP_MODE = 93, + TAG_TIM_BROADCAST_REQUEST = 94, + TAG_TIM_BROADCAST_RESPONSE = 95, + TAG_COLLOCATED_INTERFERENCE_REPORT = 96, + TAG_CHANNEL_USAGE = 97, + TAG_TIME_ZONE = 98, + TAG_DMS_REQUEST = 99, + TAG_DMS_RESPONSE = 100, + TAG_LINK_IDENTIFIER = 101, + TAG_WAKEUP_SCHEDULE = 102, + // Undefined 103 + TAG_CHANNEL_SWITCH_TIMING = 104, + TAG_PTI_CONTROL = 105, + TAG_TPU_BUFFER_STATUS = 106, + TAG_INTERWORKING = 107, + TAG_ADVERTISEMENT_PROTOCOL = 108, + TAG_EXPEDITED_BANDWIDTH_REQUEST = 109, + TAG_QOS_MAP = 110, + TAG_ROAMING_CONSORTIUM = 111, + TAG_EMERGENCY_ALERT_IDENTIFIER = 112, + TAG_MESH_CONFIGURATION = 113, + TAG_MESH_ID = 114, + TAG_MESH_LINK_METRIC_REPORT = 115, + TAG_CONGESTION_NOTIFICATION = 116, + TAG_MESH_PEERING_MANAGEMENT = 117, + TAG_MESH_CHANNEL_SWITCH_PARAMETERS = 118, + TAG_MESH_AWAKE_WINDOW = 119, + TAG_BEACON_TIMING = 120, + TAG_MCCAOP_SETUP_REQUEST = 121, + TAG_MCCAOP_SETUP_REPLY = 122, + TAG_MCCAOP_ADVERTISEMENT = 123, + TAG_MCCAOP_TEARDOWN = 124, + TAG_GANN = 125, + TAG_RANN = 126, + TAG_EXTENDED_CAPABILITIES = 127, + // Reserved 128-129 + TAG_PREQ = 130, + TAG_PREP = 131, + TAG_PERR = 132, + // Reserved 133-136 + TAG_PXU = 137, + TAG_PXUC = 138, + TAG_AUTHENTICATED_MESH_PEERING_EXCHANGE = 139, + TAG_MIC = 140, + TAG_DESTINATION_URI = 141, + TAG_U_APSD_COEXISTENCE = 142, + TAG_DMG_WAKEUP_SCHEDULE = 143, + TAG_EXTENDED_SCHEDULE = 144, + TAG_STA_AVAILABILITY = 145, + TAG_DMG_TSPEC = 146, + TAG_NEXT_DMG_ATI = 147, + // Reserved 149-150 + TAG_DMG_OPERATION = 151, + TAG_DMG_BSS_PARAMETER_CHANGE = 152, + TAG_DMG_BEAM_REFINEMENT = 153, + TAG_CHANNEL_MEASUREMENT_FEEDBACK = 154, + // Reserved 155-156 + TAG_AWAKE_WINDOW = 157, + TAG_MULTI_BAND = 158, + TAG_ADDBA_EXTENSION = 159, + TAG_NEXTPCP_LIST = 160, + TAG_PCP_HANDOVER = 161, + TAG_DMG_LINK_MARGIN = 162, + TAG_SWITCHING_STREAM = 163, + TAG_SESSION_TRANSITION = 164, + TAG_DYNAMIC_TONE_PAIRING_REPORT = 165, + TAG_CLUSTER_REPORT = 166, + TAG_RELAY_CAPABILITIES = 167, + TAG_RELAY_TRANSFER_PARAMETER_SET = 168, + TAG_BEAMLINK_MAINTENANCE = 169, + TAG_MULTIPLE_MAC_SUBLAYERS = 170, + TAG_U_PID = 171, + TAG_DMG_LINK_ADAPTATION_ACKNOWLEDGEMENT = 172, + // Reserved 173 + TAG_MCCAOP_ADVERTISEMENT_OVERVIEW = 174, + TAG_QUIET_PERIOD_REQUEST = 175, + // Reserved 176 + TAG_QUIET_PERIOD_RESPONSE = 177, + // Reserved 178-180 + TAG_QMF_POLICY = 181, + TAG_ECAPC_POLICY = 182, + TAG_CLUSTER_TIME_OFFSET = 183, + TAG_INTRA_ACCESS_CATEGORY_PRIORITY = 184, + TAG_SCS_DESCRIPTOR = 185, + TAG_QLOAD_REPORT = 186, + TAG_HCCA_TXOP_UPDATE_COUNT = 187, + TAG_HIGHER_LAYER_STREAM_ID = 188, + TAG_GCR_GROUP_ADDRESS = 189, + TAG_ANTENNA_SECTOR_ID_PATTERN = 190, + TAG_VHT_CAPABILITIES = 191, + TAG_VHT_OPERATION = 192, + TAG_EXTENDED_BSS_LOAD = 193, + TAG_WIDE_BANDWIDTH_CHANNEL_SWITCH = 194, + TAG_TRANSMIT_POWER_ENVELOPE = 195, + TAG_CHANNEL_SWITCH_WRAPPER = 196, + TAG_AID = 197, + TAG_QUIET_CHANNEL = 198, + TAG_UPSIM = 200, + TAG_REDUCED_NEIGHBOR_REPORT = 201, + TAG_TVHT_OPERATION = 202, + // Reserved 203 + TAG_DEVICE_LOCATION = 204, + TAG_WHITE_SPACE_MAP = 205, + TAG_FINE_TIMING_MEASUREMENT_PARAMETERS = 206, + // Reserved 207-220 + TAG_VENDOR_SPECIFIC = 221, + // Reserved 222-254 +}; + +/** + * A tagged parameter always consists of a tag number and length + */ +struct libwifi_tag_header { + uint8_t tag_num; + uint8_t tag_len; +} __attribute__((packed)); + +/* + * A tagged parameter will include a header as well as some body, + * depending on the tag number. The length of the body buffer is + * determined with the header.tag_len variable. + */ +struct libwifi_tagged_parameter { + struct libwifi_tag_header header; + unsigned char *body; +} __attribute__((packed)); + +/* + * A collection of total tagged parameters + */ +struct libwifi_tagged_parameters { + size_t length; + unsigned char *parameters; +} __attribute__((packed)); + +/* + * Vendor specific tagged parameters have an OUI and Sub-Type + * to determine their use + */ +struct libwifi_tag_vendor_header { + unsigned char oui[3]; + int8_t type; +} __attribute__((packed)); + +/** + * Add a tagged parameter to a list of frame tagged parameters. + * + * @param tagged_parameters A management frame's tagged parameters + * @param tagged_parameter The new tagged parameter + */ +int libwifi_add_tag(struct libwifi_tagged_parameters *tagged_parameters, + struct libwifi_tagged_parameter *tagged_parameter); + +/** + * Remove a tagged parameter from a list of frame tagged parameters. + * + * @param tagged_parameters A management frame's tagged parameters + * @param tag_number Number of the tag to remove + */ +int libwifi_remove_tag(struct libwifi_tagged_parameters *tagged_parameters, int tag_number); + +/** + * Create a tagged parameter from a tag number, length and data. + * This can be useful when generating tags on their own, for use with + * action frame body's. + * + * @param tagged_parameter A new tagged parameter struct + * @param tag_number Tagged parameter number + * @param tag_data The tag body + * @param tag_length Length of the tag body + * @return length of the created tag + */ +size_t libwifi_create_tag(struct libwifi_tagged_parameter *tagged_parameter, int tag_number, + const unsigned char *tag_data, size_t tag_length); + +/** + * Free a tagged parameters body + * + * @param tagged_parameter A used tagged parameter + */ +void libwifi_free_tag(struct libwifi_tagged_parameter *tagged_parameter); + +/** + * Dump a tagged parameter into a raw buffer, for use with other buffers + * or injection. + * + * @param tag A used tagged parameter struct + * @param buf A buffer for the raw data + * @param buf_len Length of buf + */ +size_t libwifi_dump_tag(struct libwifi_tagged_parameter *tag, unsigned char *buf, size_t buf_len); + +/** + * Add a tagged parameter via tag number and data to a management frame. + * + * @param tagged_parameters A management frame's tagged parameters + * @param tag_number Tagged parameter to add + * @param tag_data Data to copy into new tag + * @param tag_length Length of the new tag + * @return 0 on success, negative number on error + */ +int libwifi_quick_add_tag(struct libwifi_tagged_parameters *tagged_parameters, int tag_number, + const unsigned char *tag_data, size_t tag_length); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "tag_iterator.h" + +#include +#include +#include + +int libwifi_tag_iterator_init(struct libwifi_tag_iterator *it, const void *tags_start, size_t data_len) { + it->tag_header = (struct libwifi_tag_header *) tags_start; + if (it->tag_header->tag_len < 0) { + return -EINVAL; + } + + it->tag_data = (unsigned char *) tags_start + sizeof(struct libwifi_tag_header); + it->_next_tag_header = (struct libwifi_tag_header *) (it->tag_data + it->tag_header->tag_len); + it->_frame_end = (unsigned char *) (tags_start) + data_len - 1; + + return 0; +} + +int libwifi_tag_iterator_next(struct libwifi_tag_iterator *it) { + unsigned char *next_th = (unsigned char *) it->_next_tag_header; + if (next_th >= it->_frame_end) { + return -1; + } + + it->tag_header = it->_next_tag_header; + if (it->tag_header->tag_len < 0) { + return -1; + } + + unsigned long bytes_left = (char *) it->_frame_end - (char *) it->tag_header; + if (it->tag_header->tag_len >= bytes_left) { + return -1; + } + + it->tag_data = ((unsigned char *) (it->tag_header)) + sizeof(struct libwifi_tag_header); + it->_next_tag_header = (struct libwifi_tag_header *) (it->tag_data + it->tag_header->tag_len); + + return it->tag_header->tag_num; +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_TAGITERATOR_H +#define LIBWIFI_CORE_TAGITERATOR_H + +#include "../misc/byteswap.h" +#include "frame.h" +#include "tag.h" +#include + +/** + * A libwifi_tag_iterator is used to iterate through a list of tagged parameters + * in a wifi frame. + */ +struct libwifi_tag_iterator { + struct libwifi_tag_header *tag_header; + const unsigned char *tag_data; + struct libwifi_tag_header *_next_tag_header; + const unsigned char *_frame_end; +}; + +/** + * Initialise a libwifi frame tag iterator. + * + * @param it A libwifi tag iterator struct + * @param tags_start The beginning of a frame's tag data + * @param data_len The total length of the frame's tag data + * @return negative number on error, zero on success + */ +int libwifi_tag_iterator_init(struct libwifi_tag_iterator *it, const void *tags_start, size_t data_len); + +/** + * Iterate towards the next tagged parameter in a libwifi tag iterator. + * + * @param A libwifi tag iterator sturct, after being initalised + * @return The tag number of the next tag + */ +int libwifi_tag_iterator_next(struct libwifi_tag_iterator *it); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_BYTESWAP_H +#define LIBWIFI_CORE_BYTESWAP_H + +#include + +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define BYTESWAP16(x) x +#define BYTESWAP32(x) x +#define BYTESWAP64(x) x +#else +#define BYTESWAP16(x) (__bswap_16(x)) +#define BYTESWAP32(x) (__bswap_32(x)) +#define BYTESWAP64(x) (__bswap_32(x)) +#endif + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "epoch.h" +#include + +unsigned long long libwifi_get_epoch(void) { + struct timespec spec; + clock_gettime(CLOCK_REALTIME, &spec); + return spec.tv_sec * 1000 + spec.tv_nsec / 1000; +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_EPOCH_H +#define LIBWIFI_CORE_EPOCH_H + +/** + * Get the current system time in epoch. + * + * @return current time in unix epoch. + */ +unsigned long long libwifi_get_epoch(void); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_LLC_H +#define LIBWIFI_CORE_LLC_H + +#include + +#define XEROX_OUI "\x00\x00\x00" + +#define LLC_TYPE_AUTH 0x888E + +struct libwifi_logical_link_ctrl { + uint8_t dsap; + uint8_t ssap; + uint8_t control; + unsigned char oui[3]; + uint16_t type; +} __attribute__((packed)); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_RADIOTAP_H +#define LIBWIFI_CORE_RADIOTAP_H + +#include + +#define LIBWIFI_MAX_RADIOTAP_LEN 128 +#define LIBWIFI_MAX_RADIOTAP_ANTENNAS 16 + +/** + * A channel field in radiotap consists of a 2-byte wide flags + * sub-field and a 2-byte wide frequency field + */ +struct libwifi_radiotap_channel { + uint16_t flags; + uint16_t freq; +} __attribute__((packed)); + +/** + * The radiotap antenna field consists of an antenna number and signal in dBm + */ +struct libwifi_radiotap_antenna { + uint8_t antenna_number; + int8_t signal; +} __attribute__((packed)); + +/** + * The radiotap MCS field is made up of 3 2-byte fields. + */ +struct libwifi_radiotap_mcs { + uint8_t known; + uint8_t flags; + uint8_t mcs; +} __attribute__((packed)); + +/** + * The radiotap timestamp field consists of a timestamp field, accuracy, unit and flags. + */ +struct libwifi_radiotap_timestamp { + uint64_t timestamp; + uint16_t accuracy; + uint8_t unit; + uint8_t flags; +} __attribute__((packed)); + +struct libwifi_radiotap_info { + // Header + uint32_t present; + // Body + struct libwifi_radiotap_channel channel; + int8_t rate_raw; + float rate; + uint8_t antenna_count; + struct libwifi_radiotap_antenna antennas[LIBWIFI_MAX_RADIOTAP_ANTENNAS]; + int8_t signal; + uint8_t flags; + uint32_t extended_flags; + uint16_t rx_flags; + uint16_t tx_flags; + struct libwifi_radiotap_mcs mcs; + int8_t tx_power; + struct libwifi_radiotap_timestamp timestamp; + uint8_t rts_retries; + uint8_t data_retries; + // Other + uint8_t length; +} __attribute__((packed)); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_SECURITY_H +#define LIBWIFI_CORE_SECURITY_H + +#include + +/* 802.1X Key Information Field Values */ +#define EAPOL_KEY_INFO_M1 0x008A +#define EAPOL_KEY_INFO_M2 0x010A +#define EAPOL_KEY_INFO_M3 0x13CA +#define EAPOL_KEY_INFO_M4 0x030A + +/* Sane maximum value for Cipher Suite Count */ +#define LIBWIFI_MAX_CIPHER_SUITES 6 + +/* Cipher Suite OUIs for WPA and RSN */ +#define MICROSOFT_OUI "\x00\x50\xF2" +#define CIPHER_SUITE_OUI "\x00\x0F\xAC" + +/* Common Microsoft Vendor Types */ +#define MICROSOFT_OUI_TYPE_WPA 1 +#define MICROSOFT_OUI_TYPE_WMM 2 +#define MICROSOFT_OUI_TYPE_WPS 4 + +/* Cipher Suite Values */ +#define CIPHER_SUITE_GROUP 0 /* WPA1/2 */ +#define CIPHER_SUITE_WEP40 1 /* WEP */ +#define CIPHER_SUITE_TKIP 2 /* WPA1/2 */ +#define CIPHER_SUITE_RESERVED 3 /* WPA1/2 */ +#define CIPHER_SUITE_CCMP128 4 /* WPA2 */ +#define CIPHER_SUITE_WEP104 5 /* WEP */ +#define CIPHER_SUITE_BIP_CMAC128 6 /* WPA2 */ +#define CIPHER_SUITE_NOTALLOWED 7 /* WPA2 */ +#define CIPHER_SUITE_GCMP128 8 /* WPA3 */ +#define CIPHER_SUITE_GCMP256 9 /* WPA3 */ +#define CIPHER_SUITE_CCMP256 10 /* WPA3 */ +#define CIPHER_SUITE_BIP_GMAC128 11 /* WPA3 */ +#define CIPHER_SUITE_BIP_GMAC256 12 /* WPA3 */ +#define CIPHER_SUITE_BIP_CMAC256 13 /* WPA3 */ + +/* Auth Key Management Suite Values */ +#define AKM_SUITE_RESERVED 0 /* WPA1/2 */ +#define AKM_SUITE_1X 1 /* WPA1/2 */ +#define AKM_SUITE_PSK 2 /* WPA1/2 */ +#define AKM_SUITE_1X_FT 3 /* WPA1/2 */ +#define AKM_SUITE_PSK_FT 4 /* WPA2 */ +#define AKM_SUITE_1X_SHA256 5 /* WPA2 */ +#define AKM_SUITE_PSK_SHA256 6 /* WPA2 */ +#define AKM_SUITE_TDLS 7 /* WPA2 */ +#define AKM_SUITE_SAE 8 /* WPA3 */ +#define AKM_SUITE_SAE_FT 9 /* WPA3 */ +#define AKM_SUITE_AP_PEER 10 /* WPA3 */ +#define AKM_SUITE_1X_SUITEB_SHA256 11 /* WPA3 */ +#define AKM_SUITE_1X_SUITEB_SHA384 12 /* WPA3 */ +#define AKM_SUITE_1X_FT_SHA384 13 /* WPA3 */ +#define AKM_SUITE_FILS_SHA256 14 /* WPA3 */ +#define AKM_SUITE_FILS_SHA384 15 /* WPA3 */ +#define AKM_SUITE_FILS_SHA256_FT 16 /* WPA3 */ +#define AKM_SUITE_FILS_SHA384_FT 17 /* WPA3 */ +#define AKM_SUITE_OWE 18 /* WPA3 */ +#define AKM_PSK_SHA384_FT 19 /* WPA3 */ +#define AKM_PSK_SHA384 20 /* WPA3 */ + +/* Authentication Scheme Values */ +#define AUTH_OPEN 0 +#define AUTH_SHARED_KEY 1 +#define AUTH_FAST_BSS 2 +#define AUTH_SAE 3 +#define AUTH_VENDOR 65535 + +/* libwifi Security Type Values for libwifi_bss encryption_info */ +#define WEP (1ULL << 1) +#define WPA (1ULL << 2) +#define WPA2 (1ULL << 3) +#define WPA3 (1ULL << 4) + +/* libwifi Group or Multicast Cipher Values for libwifi_bss encryption_info */ +#define LIBWIFI_GROUP_CIPHER_SUITE_WEP40 (1ULL << 5) +#define LIBWIFI_GROUP_CIPHER_SUITE_TKIP (1ULL << 6) +#define LIBWIFI_GROUP_CIPHER_SUITE_RESERVED (1ULL << 7) +#define LIBWIFI_GROUP_CIPHER_SUITE_CCMP128 (1ULL << 8) +#define LIBWIFI_GROUP_CIPHER_SUITE_WEP104 (1ULL << 9) +#define LIBWIFI_GROUP_CIPHER_SUITE_BIP_CMAC128 (1ULL << 10) +#define LIBWIFI_GROUP_CIPHER_SUITE_NOTALLOWED (1ULL << 11) +#define LIBWIFI_GROUP_CIPHER_SUITE_GCMP128 (1ULL << 12) +#define LIBWIFI_GROUP_CIPHER_SUITE_GCMP256 (1ULL << 13) +#define LIBWIFI_GROUP_CIPHER_SUITE_CCMP256 (1ULL << 14) +#define LIBWIFI_GROUP_CIPHER_SUITE_BIP_GMAC128 (1ULL << 15) +#define LIBWIFI_GROUP_CIPHER_SUITE_BIP_GMAC256 (1ULL << 16) +#define LIBWIFI_GROUP_CIPHER_SUITE_BIP_CMAC256 (1ULL << 17) + +/* libwifi Pairwise or Unicast Cipher Values for libwifi_bss encryption_info */ +#define LIBWIFI_PAIRWISE_SUITE_GROUP (1ULL << 18) +#define LIBWIFI_PAIRWISE_CIPHER_SUITE_WEP40 (1ULL << 19) +#define LIBWIFI_PAIRWISE_CIPHER_SUITE_TKIP (1ULL << 20) +#define LIBWIFI_PAIRWISE_CIPHER_SUITE_RESERVED (1ULL << 21) +#define LIBWIFI_PAIRWISE_CIPHER_SUITE_CCMP128 (1ULL << 22) +#define LIBWIFI_PAIRWISE_CIPHER_SUITE_WEP104 (1ULL << 23) +#define LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_CMAC128 (1ULL << 24) +#define LIBWIFI_PAIRWISE_CIPHER_SUITE_NOTALLOWED (1ULL << 25) +#define LIBWIFI_PAIRWISE_CIPHER_SUITE_GCMP128 (1ULL << 26) +#define LIBWIFI_PAIRWISE_CIPHER_SUITE_GCMP256 (1ULL << 27) +#define LIBWIFI_PAIRWISE_CIPHER_SUITE_CCMP256 (1ULL << 28) +#define LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_GMAC128 (1ULL << 29) +#define LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_GMAC256 (1ULL << 30) +#define LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_CMAC256 (1ULL << 31) + +/* libwifi Auth Key Management Values for libwifi_bss encryption_info */ +#define LIBWIFI_AKM_SUITE_RESERVED (1ULL << 32) +#define LIBWIFI_AKM_SUITE_1X (1ULL << 33) +#define LIBWIFI_AKM_SUITE_PSK (1ULL << 34) +#define LIBWIFI_AKM_SUITE_1X_FT (1ULL << 35) +#define LIBWIFI_AKM_SUITE_PSK_FT (1ULL << 36) +#define LIBWIFI_AKM_SUITE_1X_SHA256 (1ULL << 37) +#define LIBWIFI_AKM_SUITE_PSK_SHA256 (1ULL << 39) +#define LIBWIFI_AKM_SUITE_TDLS (1ULL << 40) +#define LIBWIFI_AKM_SUITE_SAE (1ULL << 41) +#define LIBWIFI_AKM_SUITE_SAE_FT (1ULL << 42) +#define LIBWIFI_AKM_SUITE_AP_PEER (1ULL << 43) +#define LIBWIFI_AKM_SUITE_1X_SUITEB_SHA256 (1ULL << 44) +#define LIBWIFI_AKM_SUITE_1X_SUITEB_SHA384 (1ULL << 45) +#define LIBWIFI_AKM_SUITE_1X_FT_SHA384 (1ULL << 46) +#define LIBWIFI_AKM_SUITE_FILS_SHA256 (1ULL << 47) +#define LIBWIFI_AKM_SUITE_FILS_SHA384 (1ULL << 48) +#define LIBWIFI_AKM_SUITE_FILS_SHA256_FT (1ULL << 49) +#define LIBWIFI_AKM_SUITE_FILS_SHA384_FT (1ULL << 50) +#define LIBWIFI_AKM_SUITE_OWE (1ULL << 51) +#define LIBWIFI_AKM_PSK_SHA384_FT (1ULL << 52) +#define LIBWIFI_AKM_PSK_SHA384 (1ULL << 53) + +/* libwifi Authentication Scheme Values for libwifi_bss encryption_info */ +#define LIBWIFI_AUTH_OPEN (1ULL << 54) +#define LIBWIFI_AUTH_SHARED_KEY (1ULL << 55) +#define LIBWIFI_AUTH_FAST_BSS (1ULL << 56) +#define LIBWIFI_AUTH_SAE (1ULL << 57) +#define LIBWIFI_AUTH_VENDOR (1ULL << 58) + +/* libwifi RSN Capability flags */ +#define LIBWIFI_RSN_CAPAB_PREAUTH (1 << 0) +#define LIBWIFI_RSN_CAPAB_PAIRWISE (1 << 1) +#define LIBWIFI_RSN_CAPAB_PTKSA_REPLAY (1 << 2 | 1 << 3) +#define LIBWIFI_RSN_CAPAB_GTKSA_REPLAY (1 << 4 | 1 << 5) +#define LIBWIFI_RSN_CAPAB_MFP_REQUIRED (1 << 6) +#define LIBWIFI_RSN_CAPAB_MFP_CAPABLE (1 << 7) +#define LIBWIFI_RSN_CAPAB_JOINT_RSNA (1 << 8) +#define LIBWIFI_RSN_CAPAB_PEERKEY (1 << 9) +#define LIBWIFI_RSN_CAPAB_EXT_KEY_ID (1 << 13) + +/** + * libwifi Representation of a WPA or RSN cipher suite + * ┌────────────────────────┬────────────┐ + * │ OUI │ Suite Type │ + * ├────────────────────────┼────────────┤ + * │ 3 Bytes │ 1 Byte │ + * └────────────────────────┴────────────┘ + * + */ +struct libwifi_cipher_suite { + unsigned char oui[3]; + uint8_t suite_type; +} __attribute__((packed)); + +/** + * libwifi Representation of a Microsoft WPA Information Element + * ┌───────────────────────────────────┐ + * │ Version │ ── 2 Bytes + * ├───────────────────────────────────┤ + * │ Multicast Cipher Suite │ ── 4 Bytes + * ├───────────────────────────────────┤ + * │ Unicast Cipher Suite Count │ ── 2 Bytes + * ├───────────────────────────────────┤ + * │ Unicast Cipher Suites │ ── 4 to 12 Bytes + * ├───────────────────────────────────┤ + * │ Auth Key Management Suite Count │ ── 2 Bytes + * ├───────────────────────────────────┤ + * │ Auth Key Management Suites │ ── 4 to 12 Bytes + * └───────────────────────────────────┘ + */ +struct libwifi_wpa_info { + uint16_t wpa_version; + struct libwifi_cipher_suite multicast_cipher_suite; + uint16_t num_unicast_cipher_suites; + struct libwifi_cipher_suite unicast_cipher_suites[LIBWIFI_MAX_CIPHER_SUITES]; + uint16_t num_auth_key_mgmt_suites; + struct libwifi_cipher_suite auth_key_mgmt_suites[LIBWIFI_MAX_CIPHER_SUITES]; +} __attribute__((packed)); + +/** + * libwifi Representation of a 802.11 RSN Information Element + * ┌───────────────────────────────────┐ + * │ Version │ ── 2 Bytes + * ├───────────────────────────────────┤ + * │ Group Cipher Suite │ ── 4 Bytes + * ├───────────────────────────────────┤ + * │ Pairwise Cipher Suite Count │ ── 2 Bytes + * ├───────────────────────────────────┤ + * │ Pairwise Cipher Suites │ ── 4 to 12 Bytes + * ├───────────────────────────────────┤ + * │ Auth Key Management Suite Count │ ── 2 Bytes + * ├───────────────────────────────────┤ + * │ Auth Key Management Suites │ ── 4 to 12 Bytes + * ├───────────────────────────────────┤ + * │ RSN Capabilities │ ── 2 Bytes + * └───────────────────────────────────┘ + */ +struct libwifi_rsn_info { + uint16_t rsn_version; + struct libwifi_cipher_suite group_cipher_suite; + int num_pairwise_cipher_suites; + struct libwifi_cipher_suite pairwise_cipher_suites[LIBWIFI_MAX_CIPHER_SUITES]; + int num_auth_key_mgmt_suites; + struct libwifi_cipher_suite auth_key_mgmt_suites[LIBWIFI_MAX_CIPHER_SUITES]; + uint16_t rsn_capabilities; +} __attribute__((packed)); + +/* + * libwifi Representation of the 802.1X/EAPOL Key Information section + * ┌───────────────────────────────────┐ + * │ Key Information │ ── 2 Bytes + * ├───────────────────────────────────┤ + * │ Key Length │ ── 2 Bytes + * ├───────────────────────────────────┤ + * │ Replay Counter │ ── 8 Bytes + * ├───────────────────────────────────┤ + * │ WPA Key Nonce │ ── 32 Bytes + * ├───────────────────────────────────┤ + * │ WPA Key IV │ ── 16 Bytes + * ├───────────────────────────────────┤ + * │ WPA Key RSC │ ── 8 Bytes + * ├───────────────────────────────────┤ + * │ WPA Key ID │ ── 8 Bytes + * ├───────────────────────────────────┤ + * │ WPA Key MIC │ ── 16 Bytes + * ├───────────────────────────────────┤ + * │ WPA Key Data Length │ ── 4 Bytes + * ├───────────────────────────────────┤ + * │ WPA Key Data │ ── Variable + * └───────────────────────────────────┘ + */ +struct libwifi_wpa_key_info { + uint16_t information; + uint16_t key_length; + uint64_t replay_counter; + unsigned char nonce[32]; + unsigned char iv[16]; + unsigned char rsc[8]; + unsigned char id[8]; + unsigned char mic[16]; + uint16_t key_data_length; + unsigned char *key_data; +} __attribute__((packed)); + +/** + * libwifi Representation of the encapsulating 802.1X data in an EAPOL frame + * ┌─────────────────┐ + * │ Version │ ── 1 Byte + * ├─────────────────┤ + * │ Type │ ── 1 Byte + * ├─────────────────┤ + * │ Length │ ── 2 Bytes + * ├─────────────────┤ + * │ Descriptor │ ── 1 Byte + * ├─────────────────┤ + * │ Key Information │ ── See libwifi_wpa_key_info + * └─────────────────┘ + */ +struct libwifi_wpa_auth_data { + uint8_t version; + uint8_t type; + uint16_t length; + uint8_t descriptor; + struct libwifi_wpa_key_info key_info; +} __attribute__((packed)); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_CORE_TYPES_H +#define LIBWIFI_CORE_TYPES_H + +#include "../../core/misc/byteswap.h" + +/* 802.11 Management Frame "reason code" fixed parameter values */ +enum libwifi_reason_codes { + REASON_UNSPECIFIED_FAILURE = 1, + REASON_PREVIOUS_AUTH_INVALID = 2, + REASON_STA_LEAVING_ESS = 3, + REASON_INACTIVE = 4, + REASON_TOO_MANY_STAS = 5, + REASON_CLASS_2_FRAME = 6, + REASON_CLASS_3_FRAME = 7, + REASON_STA_LEAVING_BSS = 8, + REASON_STA_REQUESTING_REASSOC_NOT_AUTHED = 9, + REASON_UNNACCEPTABLE_POWER_CAPABILITY = 10, + REASON_UNNACCEPTABLE_CHANNELS = 11, + REASON_BSS_TRANSITION_MGMT = 12, + REASON_INVALID_ELEMENT = 13, + REASON_MIC_FAILURE = 14, + REASON_FOURWAY_HANDSHAKE_TIMEOUT = 15, + REASON_GROUPKEY_HANDSHAKE_TIMEOUT = 16, + REASON_INVALID_FOURWAY = 17, + REASON_INVALID_GROUP_CIPHER = 18, + REASON_INVALID_PAIRWISE_CIPHER = 19, + REASON_INVALID_AKMP = 20, + REASON_UNSUPPORTED_RSNE_VERSION = 21, + REASON_INVALID_RSNE_CAPABILITIES = 22, + REASON_INVALID_8021X_AUTH = 23, + REASON_CIPHER_SUITE_REJECTED = 24, + REASON_TDLS_DIRECT_LINK_TEARDOWN_UNREACHABLE = 25, + REASON_TDLS_DIRECT_LINK_TEARDOWN_UNSPECIFIED = 26, + REASON_SSP_REQUEST = 27, + REASON_LACKS_SSP_ROAMING = 28, + REASON_CIPHER_OR_AKM_REQUIRED = 29, + REASON_SERVICE_NOT_AUTHORIZED = 30, + REASON_SERVICE_CHANGE_PRECLUDES_TS = 31, + REASON_UNSPECIFIED_QOS = 32, + REASON_INSUFFICIENT_BANDWIDTH = 33, + REASON_EXCESSIVE_ACKS_REQUIRED = 34, + REASON_TXOPS_EXCEEDED = 35, + REASON_STA_LEAVING = 36, + REASON_END_TS = 37, + REASON_UNKNOWN_TS_OR_BA = 38, + REASON_TIMEOUT = 39, + REASON_PEERKEY_MISMATCH = 45, + REASON_PEER_INITIATED = 46, + REASON_AP_INITIATED = 47, + REASON_INVALID_FT_ACTION_FRAMECOUNT = 48, + REASON_INVALID_PMKI = 49, + REASON_INVALID_MDE = 50, + REASON_INVALID_FTE = 51, + REASON_MESH_PEERING_CANCELED = 52, + REASON_MESH_MAX_PEERS = 53, + REASON_MESH_CONFIGURATION_POLICY_VIOLATION = 54, + REASON_MESH_CLOSE_RCVD = 55, + REASON_MESH_MAX_RETRIES = 56, + REASON_MESH_CONFIRM_TIMEOUT = 57, + REASON_MESH_INVALID_GTK = 58, + REASON_MESH_INCONSISTENT_PARAMETERS = 59, + REASON_MESH_INVALID_SECURITY_CAPABILITY = 60, + REASON_MESH_PATH_ERROR_NO_PROXY_INFORMATION = 61, + REASON_MESH_PATH_ERROR_NO_FORWARDING_INFORMATION = 62, + REASON_MESH_PATH_ERROR_DESTINATION_UNREACHABLE = 63, + REASON_MAC_ADDRESS_ALREADY_EXISTS_IN_MBSS = 64, + REASON_MESH_CHANNEL_SWITCH_REGULATORY_REQUIREMENTS = 65, + REASON_MESH_CHANNEL_SWITCH_UNSPECIFIED = 66, +}; + +/* 802.11 Management Frame "status code" fixed parameter values */ +enum libwifi_status_codes { + STATUS_SUCCESS = 0, + STATUS_REFUSED = 1, + STATUS_TDLS_REJECTED_ALTERNATIVE_PROVIDED = 2, + // Reserved = 4, + STATUS_SECURITY_DISABLED = 5, + STATUS_UNACCEPTABLE_LIFETIME = 6, + STATUS_NOT_IN_SAME_BSS = 7, + // Reserved = 8, + // Reserved = 9, + STATUS_REFUSED_CAPABILITIES_MISMATCH = 10, + STATUS_DENIED_NO_ASSOCIATION_EXISTS = 11, + STATUS_DENIED_OTHER_REASON = 12, + STATUS_UNSUPPORTED_AUTH_ALGORITHM = 13, + STATUS_TRANSACTION_SEQUENCE_ERROR = 14, + STATUS_CHALLENGE_FAILURE = 15, + STATUS_REJECTED_SEQUENCE_TIMEOUT = 16, + STATUS_DENIED_NO_MORE_STAS = 17, + STATUS_REFUSED_BASIC_RATES_MISMATCH = 18, + STATUS_DENIED_NO_SHORT_PREAMBLE_SUPPORT = 19, + // Reserved = 20, + // Reserved = 21, + STATUS_REJECTED_SPECTRUM_MANAGEMENT_REQUIRED = 22, + STATUS_REJECTED_BAD_POWER_CAPABILITY = 23, + STATUS_REJECTED_BAD_SUPPORTED_CHANNELS = 24, + STATUS_DENIED_NO_SHORT_SLOT_TIME_SUPPORT = 25, + // Reserved = 26, + STATUS_DENIED_NO_HT_SUPPORT = 27, + STATUS_R0KH_UNREACHABLE = 28, + STATUS_DENIED_PCO_TIME_NOT_SUPPORTED = 29, + STATUS_REFUSED_TEMPORARILY = 30, + STATUS_ROBUST_MANAGEMENT_POLICY_VIOLATION = 31, + STATUS_UNSPECIFIED_QOS_FAILURE = 32, + STATUS_DENIED_INSUFFICIENT_BANDWIDTH = 33, + STATUS_DENIED_POOR_CHANNEL_CONDITIONS = 34, + STATUS_DENIED_QOS_NOT_SUPPORTED = 35, + // Reserved = 36, + STATUS_REQUEST_DECLINED = 37, + STATUS_INVALID_PARAMETERS = 38, + STATUS_REJECTED_WITH_SUGGESTED_CHANGES = 39, + STATUS_STATUS_INVALID_ELEMENT = 40, + STATUS_STATUS_INVALID_GROUP_CIPHER = 41, + STATUS_STATUS_INVALID_PAIRWISE_CIPHER = 42, + STATUS_STATUS_INVALID_AKMP = 43, + STATUS_UNSUPPORTED_RSNE_VERSION = 44, + STATUS_INVALID_RSNE_CAPABILITIES = 45, + STATUS_STATUS_CIPHER_OUT_OF_POLICY = 46, + STATUS_REJECTED_FOR_DELAY_PERIOD = 47, + STATUS_DLS_NOT_ALLOWED = 48, + STATUS_NOT_PRESENT = 49, + STATUS_NOT_QOS_STA = 50, + STATUS_DENIED_LISTEN_INTERVAL_TOO_LARGE = 51, + STATUS_STATUS_INVALID_FT_ACTION_FRAME_COUNT = 52, + STATUS_STATUS_INVALID_PMKID = 53, + STATUS_STATUS_INVALID_MDE = 54, + STATUS_STATUS_INVALID_FTE = 55, + STATUS_REQUESTED_TCLAS_NOT_SUPPORTED = 56, + STATUS_INSUFFICIENT_TCLAS_PROCESSING_RESOURCES = 57, + STATUS_TRY_ANOTHER_BSS = 58, + STATUS_GAS_ADVERTISEMENT_PROTOCOL_NOT_SUPPORTED = 59, + STATUS_NO_OUTSTANDING_GAS_REQUEST = 60, + STATUS_GAS_RESPONSE_NOT_RECEIVED_FROM = 61, + STATUS_GAS_QUERY_TIMEOUT = 62, + STATUS_GAS_QUERY_RESPONSE_TOO_ = 63, + STATUS_REJECTED_HOME_WITH_SUGGESTED_CHANGES = 64, + STATUS_SERVER_UNREACHABLE = 65, + // Reserved = 66, + STATUS_REJECTED_FOR_SSP_PERMISSIONS = 67, + STATUS_REFUSED_UNAUTHENTICATED_ACCESS_NOT_SUPPORTED = 68, + // Reserved = 69, + // Reserved = 70, + // Reserved = 71, + STATUS_INVALID_RSNE = 72, + STATUS_U_APSD_COEXISTANCE_NOT_SUPPORTED = 73, + STATUS_U_APSD_COEX_MODE_NOT_SUPPORTED = 74, + STATUS_BAD_INTERVAL_WITH_U_APSD_COEX = 75, + STATUS_ANTI_CLOGGING_TOKEN_REQUIRED = 76, + STATUS_UNSUPPORTED_FINITE_CYCLIC_GROUP = 77, + STATUS_CANNOT_FIND_ALTERNATIVE_TBTT = 78, + STATUS_TRANSMISSION_FAILURE = 79, + STATUS_REQUESTED_TCLAS_NOT_SUPPORTED_2 = 80, + STATUS_TCLAS_RESOURCES_EXHAUSTED = 81, + STATUS_REJECTED_WITH_SUGGESTED_BSS_TRANSITION = 82, + STATUS_REJECT_WITH_SCHEDULE = 83, + STATUS_REJECT_NO_WAKEUP_SPECIFIED = 84, + STATUS_SUCCESS_POWER_SAVE_MODE = 85, + STATUS_PENDING_ADMITTING_FST_SESSION = 86, + STATUS_PERFORMING_FST_NOW = 87, + STATUS_PENDING_GAP_IN_BA_WINDOW = 88, + STATUS_REJECT_U_PID_SETTING = 89, + // Reserved = 90, + // Reserved = 91, + STATUS_REFUSED_EXTERNAL_REASON = 92, + STATUS_REFUSED_AP_OUT_OF_MEMORY = 93, + STATUS_REJECTED_EMERGENCY_SERVICES_NOT_SUPPORTED = 94, + STATUS_QUERY_RESPONSE_OUTSTANDING = 95, + STATUS_REJECT_DSE_BAND = 96, + STATUS_TCLAS_PROCESSING_TERMINATED = 97, + STATUS_TS_SCHEDULE_CONFLICT = 98, + STATUS_DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL = 99, + STATUS_MCCAOP_RESERVATION_CONFLICT = 100, + STATUS_MAF_LIMIT_EXCEEDED = 101, + STATUS_MCCA_TRACK_LIMIT_EXCEEDED = 102, + STATUS_DENIED_DUE_TO_SPECTRUM_MANAGEMENT = 103, + STATUS_DENIED_VHT_NOT_SUPPORTED = 104, + STATUS_ENABLEMENT_DENIED = 105, + STATUS_RESTRICTION_FROM_AUTHORIZED_GDB = 106, + STATUS_AUTHORIZATION_DEENABLED = 107, + // Reserved = 108–65535 +}; + +/* Defined capabilities_information fixed parameter values */ +#define libwifi_check_capabilities(x, cap) (BYTESWAP16(x) & (1 << cap)) +enum libwifi_capabilities { + CAPABILITIES_ESS = 0, + CAPABILITIES_IBSS = 1, + CAPABILITIES_POLL = 2, + CAPABILITIES_POLL_REQ = 3, + CAPABILITIES_PRIVACY = 4, + CAPABILITIES_SHORT_PREAMBLE = 5, + CAPABILITIES_PBCC = 6, + CAPABILITIES_CHAN_AGILITY = 7, + CAPABILITIES_SPECTRUM_AGILITY = 8 & (8 >> 1), + CAPABILITIES_SHORT_SLOT = 10, + CAPABILITIES_POWER_SAVE = 11, + CAPABILITIES_MEASUREMENT = 12, + CAPABILITIES_DSSS_OFDM = 13, + CAPABILITIES_DELAYED_ACK = 14, + CAPABILITIES_IMMEDIATE_ACK = 15, +}; + +#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 @@ +Copyright (c) 2007-2009 Andy Green +Copyright (c) 2007-2009 Johannes Berg + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 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 @@ +#include +#include +#include + +#if defined(linux) || defined(Linux) || defined(__linux__) || defined(__linux) || defined(__gnu_linux__) +#include +#if defined(__UCLIBC__) +#include +#ifndef le16toh +#define le16toh __le16_to_cpu +#endif +#ifndef le32toh +#define le32toh __le32_to_cpu +#endif +#endif +#endif + +#if defined(__CYGWIN32__) || defined(CYGWIN) +#include +#include +#endif + +#if defined(__APPLE__) +#include +#endif + +#if defined(__FreeBSD__) || defined(__DragonFly__) || defined(__OpenBSD__) || defined(__MidnightBSD__) || \ + defined(__NetBSD__) +#include +#include +#endif + +#if defined(__SVR4) && defined(__sun__) +#include +#include +#endif + +#ifndef le16_to_cpu +#define le16_to_cpu le16toh +#endif + +#ifndef le32_to_cpu +#define le32_to_cpu le32toh +#endif + +#if defined(_MSC_VER) +// Microsoft +#define EXPORT __declspec(dllexport) +#define IMPORT __declspec(dllimport) +#elif defined(__GNUC__) || defined(__llvm__) || defined(__clang__) || defined(__INTEL_COMPILER) +#define EXPORT __attribute__((visibility("default"))) +#define IMPORT +#else +// do nothing and hope for the best? +#define EXPORT +#define IMPORT +#pragma warning Unknown dynamic link import / export semantics. +#endif + +#if defined(RADIOTAP_FAST_UNALIGNED_ACCESS) +#define get_unaligned(p) \ + __extension__({ \ + struct packed_dummy_struct { \ + typeof(*(p)) __val; \ + } __attribute__((packed)) *__ptr = (void *) (p); \ + \ + __ptr->__val; \ + }) +#else +#define get_unaligned(p) \ + __extension__({ \ + typeof(*(p)) __tmp; \ + memmove(&__tmp, (p), sizeof(*(p))); \ + __tmp; \ + }) +#endif + +#define get_unaligned_le16(p) le16_to_cpu(get_unaligned((uint16_t *) (p))) +#define get_unaligned_le32(p) le32_to_cpu(get_unaligned((uint32_t *) (p))) + +#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 @@ +/* + * Radiotap parser + * + * Copyright 2007 Andy Green + * Copyright 2009 Johannes Berg + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Alternatively, this software may be distributed under the terms of ISC + * license, see COPYING for more details. + */ +#include "platform.h" +#include "radiotap_iter.h" + +/* function prototypes and related defs are in radiotap_iter.h */ + +static const struct radiotap_align_size rtap_namespace_sizes[] = { + [IEEE80211_RADIOTAP_TSFT] = + { + .align = 8, + .size = 8, + }, + [IEEE80211_RADIOTAP_FLAGS] = + { + .align = 1, + .size = 1, + }, + [IEEE80211_RADIOTAP_RATE] = + { + .align = 1, + .size = 1, + }, + [IEEE80211_RADIOTAP_CHANNEL] = + { + .align = 2, + .size = 4, + }, + [IEEE80211_RADIOTAP_FHSS] = + { + .align = 2, + .size = 2, + }, + [IEEE80211_RADIOTAP_DBM_ANTSIGNAL] = + { + .align = 1, + .size = 1, + }, + [IEEE80211_RADIOTAP_DBM_ANTNOISE] = + { + .align = 1, + .size = 1, + }, + [IEEE80211_RADIOTAP_LOCK_QUALITY] = + { + .align = 2, + .size = 2, + }, + [IEEE80211_RADIOTAP_TX_ATTENUATION] = + { + .align = 2, + .size = 2, + }, + [IEEE80211_RADIOTAP_DB_TX_ATTENUATION] = + { + .align = 2, + .size = 2, + }, + [IEEE80211_RADIOTAP_DBM_TX_POWER] = + { + .align = 1, + .size = 1, + }, + [IEEE80211_RADIOTAP_ANTENNA] = + { + .align = 1, + .size = 1, + }, + [IEEE80211_RADIOTAP_DB_ANTSIGNAL] = + { + .align = 1, + .size = 1, + }, + [IEEE80211_RADIOTAP_DB_ANTNOISE] = + { + .align = 1, + .size = 1, + }, + [IEEE80211_RADIOTAP_RX_FLAGS] = + { + .align = 2, + .size = 2, + }, + [IEEE80211_RADIOTAP_TX_FLAGS] = + { + .align = 2, + .size = 2, + }, + [IEEE80211_RADIOTAP_RTS_RETRIES] = + { + .align = 1, + .size = 1, + }, + [IEEE80211_RADIOTAP_DATA_RETRIES] = + { + .align = 1, + .size = 1, + }, + [IEEE80211_RADIOTAP_MCS] = + { + .align = 1, + .size = 3, + }, + [IEEE80211_RADIOTAP_AMPDU_STATUS] = + { + .align = 4, + .size = 8, + }, + [IEEE80211_RADIOTAP_VHT] = + { + .align = 2, + .size = 12, + }, + [IEEE80211_RADIOTAP_TIMESTAMP] = + { + .align = 8, + .size = 12, + }, + /* + * add more here as they are defined in radiotap.h + */ +}; + +const struct ieee80211_radiotap_namespace radiotap_ns = { + .n_bits = sizeof(rtap_namespace_sizes) / sizeof(rtap_namespace_sizes[0]), + .align_size = rtap_namespace_sizes, +}; + +/** + * ieee80211_radiotap_iterator_init - radiotap parser iterator initialization + * @iterator: radiotap_iterator to initialize + * @radiotap_header: radiotap header to parse + * @max_length: total length we can parse into (eg, whole packet length) + * + * Returns: 0 or a negative error code if there is a problem. + * + * This function initializes an opaque iterator struct which can then + * be passed to ieee80211_radiotap_iterator_next() to visit every radiotap + * argument which is present in the header. It knows about extended + * present headers and handles them. + * + * How to use: + * call __ieee80211_radiotap_iterator_init() to init a semi-opaque iterator + * struct ieee80211_radiotap_iterator (no need to init the struct beforehand) + * checking for a good 0 return code. Then loop calling + * __ieee80211_radiotap_iterator_next()... it returns either 0, + * -ENOENT if there are no more args to parse, or -EINVAL if there is a problem. + * The iterator's @this_arg member points to the start of the argument + * associated with the current argument index that is present, which can be + * found in the iterator's @this_arg_index member. This arg index corresponds + * to the IEEE80211_RADIOTAP_... defines. + * + * Radiotap header length: + * You can find the CPU-endian total radiotap header length in + * iterator->max_length after executing ieee80211_radiotap_iterator_init() + * successfully. + * + * Alignment Gotcha: + * You must take care when dereferencing iterator.this_arg + * for multibyte types... the pointer is not aligned. Use + * get_unaligned((type *)iterator.this_arg) to dereference + * iterator.this_arg for type "type" safely on all arches. + * + * Example code: parse.c + */ + +EXPORT +int ieee80211_radiotap_iterator_init(struct ieee80211_radiotap_iterator *iterator, + struct ieee80211_radiotap_header *radiotap_header, int max_length, + const struct ieee80211_radiotap_vendor_namespaces *vns) { + /* must at least have the radiotap header */ + if (max_length < (int) sizeof(struct ieee80211_radiotap_header)) + return -EINVAL; + + /* Linux only supports version 0 radiotap format */ + if (radiotap_header->it_version) + return -EINVAL; + + /* sanity check for allowed length and radiotap length field */ + if (max_length < get_unaligned_le16(UNALIGNED_ADDRESS(&radiotap_header->it_len))) + return -EINVAL; + + iterator->_rtheader = radiotap_header; + iterator->_max_length = get_unaligned_le16(UNALIGNED_ADDRESS(&radiotap_header->it_len)); + iterator->_arg_index = 0; + iterator->_bitmap_shifter = get_unaligned_le32(UNALIGNED_ADDRESS(&radiotap_header->it_present)); + iterator->_arg = (uint8_t *) radiotap_header + sizeof(*radiotap_header); + iterator->_reset_on_ext = 0; +#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 9 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Waddress-of-packed-member" +#endif + iterator->_next_bitmap = UNALIGNED_ADDRESS(&radiotap_header->it_present); +#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 9 +#pragma GCC diagnostic pop +#endif + iterator->_next_bitmap++; + iterator->_vns = vns; + iterator->current_namespace = &radiotap_ns; + iterator->is_radiotap_ns = 1; +#ifdef RADIOTAP_SUPPORT_OVERRIDES + iterator->n_overrides = 0; + iterator->overrides = NULL; +#endif + + /* find payload start allowing for extended bitmap(s) */ + + if (iterator->_bitmap_shifter & (1 << IEEE80211_RADIOTAP_EXT)) { + if ((unsigned long) iterator->_arg - (unsigned long) iterator->_rtheader + sizeof(uint32_t) > + (unsigned long) iterator->_max_length) + return -EINVAL; + while (get_unaligned_le32(iterator->_arg) & (1 << IEEE80211_RADIOTAP_EXT)) { + iterator->_arg += sizeof(uint32_t); + + /* + * check for insanity where the present bitmaps + * keep claiming to extend up to or even beyond the + * stated radiotap header length + */ + + if ((unsigned long) iterator->_arg - (unsigned long) iterator->_rtheader + sizeof(uint32_t) > + (unsigned long) iterator->_max_length) + return -EINVAL; + } + + iterator->_arg += sizeof(uint32_t); + + /* + * no need to check again for blowing past stated radiotap + * header length, because ieee80211_radiotap_iterator_next + * checks it before it is dereferenced + */ + } + + iterator->this_arg = iterator->_arg; + + /* we are all initialized happily */ + + return 0; +} + +static void find_ns(struct ieee80211_radiotap_iterator *iterator, uint32_t oui, uint8_t subns) { + int i; + + iterator->current_namespace = NULL; + + if (!iterator->_vns) + return; + + for (i = 0; i < iterator->_vns->n_ns; i++) { + if (iterator->_vns->ns[i].oui != oui) + continue; + if (iterator->_vns->ns[i].subns != subns) + continue; + + iterator->current_namespace = &iterator->_vns->ns[i]; + break; + } +} + +#ifdef RADIOTAP_SUPPORT_OVERRIDES +static int find_override(struct ieee80211_radiotap_iterator *iterator, int *align, int *size) { + int i; + + if (!iterator->overrides) + return 0; + + for (i = 0; i < iterator->n_overrides; i++) { + if (iterator->_arg_index == iterator->overrides[i].field) { + *align = iterator->overrides[i].align; + *size = iterator->overrides[i].size; + if (!*align) /* erroneous override */ + return 0; + return 1; + } + } + + return 0; +} +#endif + +/** + * ieee80211_radiotap_iterator_next - return next radiotap parser iterator arg + * @iterator: radiotap_iterator to move to next arg (if any) + * + * Returns: 0 if there is an argument to handle, + * -ENOENT if there are no more args or -EINVAL + * if there is something else wrong. + * + * This function provides the next radiotap arg index (IEEE80211_RADIOTAP_*) + * in @this_arg_index and sets @this_arg to point to the + * payload for the field. It takes care of alignment handling and extended + * present fields. @this_arg can be changed by the caller (eg, + * incremented to move inside a compound argument like + * IEEE80211_RADIOTAP_CHANNEL). The args pointed to are in + * little-endian format whatever the endianness of your CPU. + * + * Alignment Gotcha: + * You must take care when dereferencing iterator.this_arg + * for multibyte types... the pointer is not aligned. Use + * get_unaligned((type *)iterator.this_arg) to dereference + * iterator.this_arg for type "type" safely on all arches. + */ + +EXPORT +int ieee80211_radiotap_iterator_next(struct ieee80211_radiotap_iterator *iterator) { + while (1) { + int hit = 0; + int pad, align, size, subns; + uint32_t oui; + + /* if no more EXT bits, that's it */ + if ((iterator->_arg_index % 32) == IEEE80211_RADIOTAP_EXT && !(iterator->_bitmap_shifter & 1)) + return -ENOENT; + + if (!(iterator->_bitmap_shifter & 1)) + goto next_entry; /* arg not present */ + + /* get alignment/size of data */ + switch (iterator->_arg_index % 32) { + case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE: + case IEEE80211_RADIOTAP_EXT: + align = 1; + size = 0; + break; + case IEEE80211_RADIOTAP_VENDOR_NAMESPACE: + align = 2; + size = 6; + break; + default: +#ifdef RADIOTAP_SUPPORT_OVERRIDES + if (find_override(iterator, &align, &size)) { + /* all set */ + } else +#endif + if (!iterator->current_namespace || + iterator->_arg_index >= iterator->current_namespace->n_bits) { + if (iterator->current_namespace == &radiotap_ns) + return -ENOENT; + align = 0; + } else { + align = iterator->current_namespace->align_size[iterator->_arg_index].align; + size = iterator->current_namespace->align_size[iterator->_arg_index].size; + } + if (!align) { + /* skip all subsequent data */ + iterator->_arg = iterator->_next_ns_data; + /* give up on this namespace */ + iterator->current_namespace = NULL; + goto next_entry; + } + break; + } + + /* + * arg is present, account for alignment padding + * + * Note that these alignments are relative to the start + * of the radiotap header. There is no guarantee + * that the radiotap header itself is aligned on any + * kind of boundary. + * + * The above is why get_unaligned() is used to dereference + * multibyte elements from the radiotap area. + */ + + pad = ((unsigned long) iterator->_arg - (unsigned long) iterator->_rtheader) & (align - 1); + + if (pad) + iterator->_arg += align - pad; + + if (iterator->_arg_index % 32 == IEEE80211_RADIOTAP_VENDOR_NAMESPACE) { + int vnslen; + + if ((unsigned long) iterator->_arg + size - (unsigned long) iterator->_rtheader > + (unsigned long) iterator->_max_length) + return -EINVAL; + + oui = (*iterator->_arg << 16) | (*(iterator->_arg + 1) << 8) | *(iterator->_arg + 2); + subns = *(iterator->_arg + 3); + + find_ns(iterator, oui, subns); + + vnslen = get_unaligned_le16(iterator->_arg + 4); + iterator->_next_ns_data = iterator->_arg + size + vnslen; + if (!iterator->current_namespace) + size += vnslen; + } + + /* + * this is what we will return to user, but we need to + * move on first so next call has something fresh to test + */ + iterator->this_arg_index = iterator->_arg_index; + iterator->this_arg = iterator->_arg; + iterator->this_arg_size = size; + + /* internally move on the size of this arg */ + iterator->_arg += size; + + /* + * check for insanity where we are given a bitmap that + * claims to have more arg content than the length of the + * radiotap section. We will normally end up equalling this + * max_length on the last arg, never exceeding it. + */ + + if ((unsigned long) iterator->_arg - (unsigned long) iterator->_rtheader > + (unsigned long) iterator->_max_length) + return -EINVAL; + + /* these special ones are valid in each bitmap word */ + switch (iterator->_arg_index % 32) { + case IEEE80211_RADIOTAP_VENDOR_NAMESPACE: + iterator->_reset_on_ext = 1; + + iterator->is_radiotap_ns = 0; + /* + * If parser didn't register this vendor + * namespace with us, allow it to show it + * as 'raw. Do do that, set argument index + * to vendor namespace. + */ + iterator->this_arg_index = IEEE80211_RADIOTAP_VENDOR_NAMESPACE; + if (!iterator->current_namespace) + hit = 1; + goto next_entry; + case IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE: + iterator->_reset_on_ext = 1; + iterator->current_namespace = &radiotap_ns; + iterator->is_radiotap_ns = 1; + goto next_entry; + case IEEE80211_RADIOTAP_EXT: + /* + * bit 31 was set, there is more + * -- move to next u32 bitmap + */ + iterator->_bitmap_shifter = get_unaligned_le32(iterator->_next_bitmap); + iterator->_next_bitmap++; + if (iterator->_reset_on_ext) + iterator->_arg_index = 0; + else + iterator->_arg_index++; + iterator->_reset_on_ext = 0; + break; + default: + /* we've got a hit! */ + hit = 1; + next_entry: + iterator->_bitmap_shifter >>= 1; + iterator->_arg_index++; + } + + /* if we found a valid arg earlier, return it now */ + if (hit) + return 0; + } +} 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 @@ +/* + * Copyright (c) 2017 Intel Deutschland GmbH + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ +#ifndef __RADIOTAP_H +#define __RADIOTAP_H + +#if defined(__APPLE__) +#include +#define bswap_16 OSSwapInt16 +#define bswap_32 OSSwapInt32 +#define bswap_64 OSSwapInt64 +#include +#ifndef le16toh +#define le16toh(x) OSSwapLittleToHostInt16(x) +#endif +#ifndef le32toh +#define le32toh(x) OSSwapLittleToHostInt32(x) +#endif +#ifndef le64toh +#define le64toh(x) OSSwapLittleToHostInt64(x) +#endif +#endif + +#include + +/** + * struct ieee82011_radiotap_header - base radiotap header + */ +struct ieee80211_radiotap_header { + /** + * @it_version: radiotap version, always 0 + */ + uint8_t it_version; + + /** + * @it_pad: padding (or alignment) + */ + uint8_t it_pad; + + /** + * @it_len: overall radiotap header length + */ + uint16_t it_len; + + /** + * @it_present: (first) present word + */ + uint32_t it_present; +} __attribute__((__packed__)); + +/* version is always 0 */ +#define PKTHDR_RADIOTAP_VERSION 0 + +extern const struct ieee80211_radiotap_namespace radiotap_ns; + +/* see the radiotap website for the descriptions */ +enum ieee80211_radiotap_presence { + IEEE80211_RADIOTAP_TSFT = 0, + IEEE80211_RADIOTAP_FLAGS = 1, + IEEE80211_RADIOTAP_RATE = 2, + IEEE80211_RADIOTAP_CHANNEL = 3, + IEEE80211_RADIOTAP_FHSS = 4, + IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, + IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, + IEEE80211_RADIOTAP_LOCK_QUALITY = 7, + IEEE80211_RADIOTAP_TX_ATTENUATION = 8, + IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, + IEEE80211_RADIOTAP_DBM_TX_POWER = 10, + IEEE80211_RADIOTAP_ANTENNA = 11, + IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, + IEEE80211_RADIOTAP_DB_ANTNOISE = 13, + IEEE80211_RADIOTAP_RX_FLAGS = 14, + IEEE80211_RADIOTAP_TX_FLAGS = 15, + IEEE80211_RADIOTAP_RTS_RETRIES = 16, + IEEE80211_RADIOTAP_DATA_RETRIES = 17, + /* 18 is XChannel, but it's not defined yet */ + IEEE80211_RADIOTAP_MCS = 19, + IEEE80211_RADIOTAP_AMPDU_STATUS = 20, + IEEE80211_RADIOTAP_VHT = 21, + IEEE80211_RADIOTAP_TIMESTAMP = 22, + + /* valid in every it_present bitmap, even vendor namespaces */ + IEEE80211_RADIOTAP_RADIOTAP_NAMESPACE = 29, + IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30, + IEEE80211_RADIOTAP_EXT = 31 +}; + +/* for IEEE80211_RADIOTAP_FLAGS */ +enum ieee80211_radiotap_flags { + IEEE80211_RADIOTAP_F_CFP = 0x01, + IEEE80211_RADIOTAP_F_SHORTPRE = 0x02, + IEEE80211_RADIOTAP_F_WEP = 0x04, + IEEE80211_RADIOTAP_F_FRAG = 0x08, + IEEE80211_RADIOTAP_F_FCS = 0x10, + IEEE80211_RADIOTAP_F_DATAPAD = 0x20, + IEEE80211_RADIOTAP_F_BADFCS = 0x40, +}; + +/* for IEEE80211_RADIOTAP_CHANNEL */ +enum ieee80211_radiotap_channel_flags { + IEEE80211_CHAN_CCK = 0x0020, + IEEE80211_CHAN_OFDM = 0x0040, + IEEE80211_CHAN_2GHZ = 0x0080, + IEEE80211_CHAN_5GHZ = 0x0100, + IEEE80211_CHAN_DYN = 0x0400, + IEEE80211_CHAN_HALF = 0x4000, + IEEE80211_CHAN_QUARTER = 0x8000, +}; + +/* for IEEE80211_RADIOTAP_RX_FLAGS */ +enum ieee80211_radiotap_rx_flags { + IEEE80211_RADIOTAP_F_RX_BADPLCP = 0x0002, +}; + +/* for IEEE80211_RADIOTAP_TX_FLAGS */ +enum ieee80211_radiotap_tx_flags { + IEEE80211_RADIOTAP_F_TX_FAIL = 0x0001, + IEEE80211_RADIOTAP_F_TX_CTS = 0x0002, + IEEE80211_RADIOTAP_F_TX_RTS = 0x0004, + IEEE80211_RADIOTAP_F_TX_NOACK = 0x0008, +}; + +/* for IEEE80211_RADIOTAP_MCS "have" flags */ +enum ieee80211_radiotap_mcs_have { + IEEE80211_RADIOTAP_MCS_HAVE_BW = 0x01, + IEEE80211_RADIOTAP_MCS_HAVE_MCS = 0x02, + IEEE80211_RADIOTAP_MCS_HAVE_GI = 0x04, + IEEE80211_RADIOTAP_MCS_HAVE_FMT = 0x08, + IEEE80211_RADIOTAP_MCS_HAVE_FEC = 0x10, + IEEE80211_RADIOTAP_MCS_HAVE_STBC = 0x20, +}; + +enum ieee80211_radiotap_mcs_flags { + IEEE80211_RADIOTAP_MCS_BW_MASK = 0x03, + IEEE80211_RADIOTAP_MCS_BW_20 = 0, + IEEE80211_RADIOTAP_MCS_BW_40 = 1, + IEEE80211_RADIOTAP_MCS_BW_20L = 2, + IEEE80211_RADIOTAP_MCS_BW_20U = 3, + + IEEE80211_RADIOTAP_MCS_SGI = 0x04, + IEEE80211_RADIOTAP_MCS_FMT_GF = 0x08, + IEEE80211_RADIOTAP_MCS_FEC_LDPC = 0x10, + IEEE80211_RADIOTAP_MCS_STBC_MASK = 0x60, + IEEE80211_RADIOTAP_MCS_STBC_1 = 1, + IEEE80211_RADIOTAP_MCS_STBC_2 = 2, + IEEE80211_RADIOTAP_MCS_STBC_3 = 3, + IEEE80211_RADIOTAP_MCS_STBC_SHIFT = 5, +}; + +/* for IEEE80211_RADIOTAP_AMPDU_STATUS */ +enum ieee80211_radiotap_ampdu_flags { + IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN = 0x0001, + IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN = 0x0002, + IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN = 0x0004, + IEEE80211_RADIOTAP_AMPDU_IS_LAST = 0x0008, + IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR = 0x0010, + IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN = 0x0020, +}; + +/* for IEEE80211_RADIOTAP_VHT */ +enum ieee80211_radiotap_vht_known { + IEEE80211_RADIOTAP_VHT_KNOWN_STBC = 0x0001, + IEEE80211_RADIOTAP_VHT_KNOWN_TXOP_PS_NA = 0x0002, + IEEE80211_RADIOTAP_VHT_KNOWN_GI = 0x0004, + IEEE80211_RADIOTAP_VHT_KNOWN_SGI_NSYM_DIS = 0x0008, + IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM = 0x0010, + IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED = 0x0020, + IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH = 0x0040, + IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID = 0x0080, + IEEE80211_RADIOTAP_VHT_KNOWN_PARTIAL_AID = 0x0100, +}; + +enum ieee80211_radiotap_vht_flags { + IEEE80211_RADIOTAP_VHT_FLAG_STBC = 0x01, + IEEE80211_RADIOTAP_VHT_FLAG_TXOP_PS_NA = 0x02, + IEEE80211_RADIOTAP_VHT_FLAG_SGI = 0x04, + IEEE80211_RADIOTAP_VHT_FLAG_SGI_NSYM_M10_9 = 0x08, + IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM = 0x10, + IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED = 0x20, +}; + +enum ieee80211_radiotap_vht_coding { + IEEE80211_RADIOTAP_CODING_LDPC_USER0 = 0x01, + IEEE80211_RADIOTAP_CODING_LDPC_USER1 = 0x02, + IEEE80211_RADIOTAP_CODING_LDPC_USER2 = 0x04, + IEEE80211_RADIOTAP_CODING_LDPC_USER3 = 0x08, +}; + +/* for IEEE80211_RADIOTAP_TIMESTAMP */ +enum ieee80211_radiotap_timestamp_unit_spos { + IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MASK = 0x000F, + IEEE80211_RADIOTAP_TIMESTAMP_UNIT_MS = 0x0000, + IEEE80211_RADIOTAP_TIMESTAMP_UNIT_US = 0x0001, + IEEE80211_RADIOTAP_TIMESTAMP_UNIT_NS = 0x0003, + IEEE80211_RADIOTAP_TIMESTAMP_SPOS_MASK = 0x00F0, + IEEE80211_RADIOTAP_TIMESTAMP_SPOS_BEGIN_MDPU = 0x0000, + IEEE80211_RADIOTAP_TIMESTAMP_SPOS_PLCP_SIG_ACQ = 0x0010, + IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_PPDU = 0x0020, + IEEE80211_RADIOTAP_TIMESTAMP_SPOS_EO_MPDU = 0x0030, + IEEE80211_RADIOTAP_TIMESTAMP_SPOS_UNKNOWN = 0x00F0, +}; + +enum ieee80211_radiotap_timestamp_flags { + IEEE80211_RADIOTAP_TIMESTAMP_FLAG_64BIT = 0x00, + IEEE80211_RADIOTAP_TIMESTAMP_FLAG_32BIT = 0x01, + IEEE80211_RADIOTAP_TIMESTAMP_FLAG_ACCURACY = 0x02, +}; + +#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 @@ +#ifndef __RADIOTAP_ITER_H +#define __RADIOTAP_ITER_H + +#include "platform.h" +#include "radiotap.h" +#include + +/* Radiotap header iteration + * implemented in radiotap.c + */ + +struct radiotap_override { + uint8_t field; + uint8_t align : 4, size : 4; +}; + +struct radiotap_align_size { + uint8_t align : 4, size : 4; +}; + +struct ieee80211_radiotap_namespace { + const struct radiotap_align_size *align_size; + int n_bits; + uint32_t oui; + uint8_t subns; +}; + +struct ieee80211_radiotap_vendor_namespaces { + const struct ieee80211_radiotap_namespace *ns; + int n_ns; +}; + +/** + * struct ieee80211_radiotap_iterator - tracks walk thru present radiotap args + * @this_arg_index: index of current arg, valid after each successful call + * to ieee80211_radiotap_iterator_next() + * @this_arg: pointer to current radiotap arg; it is valid after each + * call to ieee80211_radiotap_iterator_next() but also after + * ieee80211_radiotap_iterator_init() where it will point to + * the beginning of the actual data portion + * @this_arg_size: length of the current arg, for convenience + * @current_namespace: pointer to the current namespace definition + * (or internally %NULL if the current namespace is unknown) + * @is_radiotap_ns: indicates whether the current namespace is the default + * radiotap namespace or not + * + * @overrides: override standard radiotap fields + * @n_overrides: number of overrides + * + * @_rtheader: pointer to the radiotap header we are walking through + * @_max_length: length of radiotap header in cpu byte ordering + * @_arg_index: next argument index + * @_arg: next argument pointer + * @_next_bitmap: internal pointer to next present u32 + * @_bitmap_shifter: internal shifter for curr u32 bitmap, b0 set == arg present + * @_vns: vendor namespace definitions + * @_next_ns_data: beginning of the next namespace's data + * @_reset_on_ext: internal; reset the arg index to 0 when going to the + * next bitmap word + * + * Describes the radiotap parser state. Fields prefixed with an underscore + * must not be used by users of the parser, only by the parser internally. + */ + +struct ieee80211_radiotap_iterator { + struct ieee80211_radiotap_header *_rtheader; + const struct ieee80211_radiotap_vendor_namespaces *_vns; + const struct ieee80211_radiotap_namespace *current_namespace; + + unsigned char *_arg, *_next_ns_data; + uint32_t *_next_bitmap; + + unsigned char *this_arg; + const struct radiotap_override *overrides; /* Only for RADIOTAP_SUPPORT_OVERRIDES */ + int n_overrides; /* Only for RADIOTAP_SUPPORT_OVERRIDES */ + int this_arg_index; + int this_arg_size; + + int is_radiotap_ns; + + int _max_length; + int _arg_index; + uint32_t _bitmap_shifter; + int _reset_on_ext; +}; + +#ifdef __cplusplus +#define CALLING_CONVENTION "C" +#else +#define CALLING_CONVENTION +#endif + +IMPORT extern CALLING_CONVENTION int +ieee80211_radiotap_iterator_init(struct ieee80211_radiotap_iterator *iterator, + struct ieee80211_radiotap_header *radiotap_header, int max_length, + const struct ieee80211_radiotap_vendor_namespaces *vns); + +IMPORT extern CALLING_CONVENTION int +ieee80211_radiotap_iterator_next(struct ieee80211_radiotap_iterator *iterator); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cts.h" + +#include + +int libwifi_create_cts(struct libwifi_cts *cts, const unsigned char receiver[6], uint16_t duration) { + memset(cts, 0, sizeof(struct libwifi_cts)); + + cts->frame_header.frame_control.type = TYPE_CONTROL; + cts->frame_header.frame_control.subtype = SUBTYPE_CTS; + cts->frame_header.duration = duration; + + memcpy(cts->receiver_addr, receiver, 6); + + return 0; +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_GEN_CTS_H +#define LIBWIFI_GEN_CTS_H + +#include "../../core/frame/control/cts.h" + +/** + * Create a CTS Control frame + * + * @param cts A fresh libwifi_cts struct + * @param receiver The receiver MAC address + * @param duration The duration of the clear-to-send + */ +int libwifi_create_cts(struct libwifi_cts *cts, const unsigned char receiver[6], uint16_t duration); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "rts.h" + +#include + +int libwifi_create_rts(struct libwifi_rts *rts, const unsigned char transmitter[6], + const unsigned char receiver[6], uint16_t duration) { + memset(rts, 0, sizeof(struct libwifi_rts)); + + rts->frame_header.frame_control.type = TYPE_CONTROL; + rts->frame_header.frame_control.subtype = SUBTYPE_RTS; + rts->frame_header.duration = duration; + + memcpy(rts->transmitter_addr, transmitter, 6); + memcpy(rts->receiver_addr, receiver, 6); + + return 0; +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_GEN_RTS_H +#define LIBWIFI_GEN_RTS_H + +#include "../../core/frame/control/rts.h" + +/** + * Create a RTS Control frame + * + * @param rts A fresh libwifi_rts struct + * @param transmitter The transmitter MAC address + * @param receiver The receiver MAC address + * @param duration The duration of the clear-to-send + */ +int libwifi_create_rts(struct libwifi_rts *rts, const unsigned char transmitter[6], + const unsigned char receiver[6], uint16_t duration); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "action.h" + +#include +#include +#include + +size_t libwifi_add_action_detail(struct libwifi_action_detail *detail, const unsigned char *data, + size_t data_len) { + if (detail->detail_length != 0) { + detail->detail = realloc(detail->detail, data_len); + } else { + detail->detail = malloc(data_len); + } + + if (detail->detail == NULL) { + return -EINVAL; + } + + detail->detail_length = data_len; + + memcpy(detail->detail, data, data_len); + detail->detail_length = data_len; + + return detail->detail_length; +} + +void libwifi_free_action_detail(struct libwifi_action_detail *detail) { + if (detail->detail_length != 0) { + free(detail->detail); + detail->detail_length = 0; + } +} + +int libwifi_create_action(struct libwifi_action *action, const unsigned char receiver[6], + const unsigned char transmitter[6], uint8_t category) { + memset(action, 0, sizeof(struct libwifi_action)); + + action->frame_header.frame_control.type = TYPE_MANAGEMENT; + action->frame_header.frame_control.subtype = SUBTYPE_ACTION; + memcpy(&action->frame_header.addr1, receiver, 6); + memcpy(&action->frame_header.addr2, transmitter, 6); + memcpy(&action->frame_header.addr3, transmitter, 6); + + action->frame_header.seq_control.sequence_number = (rand() % 4096); + + action->fixed_parameters.category = category; + + return 0; +} + +int libwifi_create_action_no_ack(struct libwifi_action *action, const unsigned char receiver[6], + const unsigned char transmitter[6], uint8_t category) { + memset(action, 0, sizeof(struct libwifi_action)); + + action->frame_header.frame_control.type = TYPE_MANAGEMENT; + action->frame_header.frame_control.subtype = SUBTYPE_ACTION_NOACK; + memcpy(&action->frame_header.addr1, receiver, 6); + memcpy(&action->frame_header.addr2, transmitter, 6); + memcpy(&action->frame_header.addr3, transmitter, 6); + + action->frame_header.seq_control.sequence_number = (rand() % 4096); + + action->fixed_parameters.category = category; + + return 0; +} + +size_t libwifi_get_action_length(struct libwifi_action *action) { + return sizeof(struct libwifi_mgmt_unordered_frame_header) + sizeof(action->fixed_parameters.category) + + action->fixed_parameters.details.detail_length; +} + +size_t libwifi_dump_action(struct libwifi_action *action, unsigned char *buf, size_t buf_len) { + size_t action_len = libwifi_get_action_length(action); + if (action_len > buf_len) { + return -EINVAL; + } + + size_t offset = 0; + + memcpy(buf + offset, &action->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header)); + offset += sizeof(struct libwifi_mgmt_unordered_frame_header); + + memcpy(buf + offset, &action->fixed_parameters.category, sizeof(action->fixed_parameters.category)); + offset += sizeof(action->fixed_parameters.category); + memcpy(buf + offset, action->fixed_parameters.details.detail, + action->fixed_parameters.details.detail_length); + offset += action->fixed_parameters.details.detail_length; + + return action_len; +} + +void libwifi_free_action(struct libwifi_action *action) { + free(action->fixed_parameters.details.detail); +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_GEN_ACTION_H +#define LIBWIFI_GEN_ACTION_H + +#include "../../core/frame/management/action.h" +#include + +/** + * Create a detail for an action frame by supplying raw data and it's length. + * New data can be added to an existing libwifi_action_detail. + * + * @param detail A libwifi_action_detail struct + * @param data Raw data to be added to the libwifi_action_detail + * @param data_len Length of the raw data + * @return Length of the action + */ +size_t libwifi_add_action_detail(struct libwifi_action_detail *detail, const unsigned char *data, + size_t data_len); + +/** + * Free all memory in a given libwifi_action_detail. + * + * @param detail A used libwifi_action_detail struct + */ +void libwifi_free_action_detail(struct libwifi_action_detail *detail); + +/** + * Create a new action frame with a specified action and category. + * + * @param action A new libwifi_action struct + * @param receiver The receiver MAC address + * @param transmitter The transmitter MAC address + * @param category The action frame category + * @return zero on success + */ +int libwifi_create_action(struct libwifi_action *action, const unsigned char receiver[6], + const unsigned char transmitter[6], uint8_t category); +int libwifi_create_action_no_ack(struct libwifi_action *action, const unsigned char receiver[6], + const unsigned char transmitter[6], uint8_t category); + +/** + * Get the length of a given libwifi_action + * + * @param action A used libwifi_action struct + * @return The length of the given libwifi_action + */ +size_t libwifi_get_action_length(struct libwifi_action *action); + +/** + * Dump a given libwifi_action to a raw buffer + * + * @param action A used libwifi_action struct + * @param buf A buffer receiver + * @param buf_len The length of the given buf + * @return Bytes written to the buf + */ +size_t libwifi_dump_action(struct libwifi_action *action, unsigned char *buf, size_t buf_len); + +/** + * Free data associated to a given libwifi_action + * + * @param action A used libwifi_action struct + */ +void libwifi_free_action(struct libwifi_action *action); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "assoc_request.h" +#include "common.h" + +#include +#include +#include + +/** + * The length of an association request frame is the sum of the header length, the fixed parameters length, + * and the tagged parameters length. + */ +size_t libwifi_get_assoc_req_length(struct libwifi_assoc_req *assoc_req) { + return sizeof(assoc_req->frame_header) + sizeof(struct libwifi_assoc_req_fixed_parameters) + + assoc_req->tags.length; +} + +/** + * The generated association request frame is made with sane defaults defined in common.h. + * Two tagged parameters are also added to the association request: SSID and Channel. + */ +int libwifi_create_assoc_req(struct libwifi_assoc_req *assoc_req, const unsigned char receiver[6], + const unsigned char transmitter[6], const char *ssid, uint8_t channel) { + memset(assoc_req, 0, sizeof(struct libwifi_assoc_req)); + + assoc_req->frame_header.frame_control.type = TYPE_MANAGEMENT; + assoc_req->frame_header.frame_control.subtype = SUBTYPE_ASSOC_REQ; + memcpy(&assoc_req->frame_header.addr1, receiver, 6); + memcpy(&assoc_req->frame_header.addr2, transmitter, 6); + memcpy(&assoc_req->frame_header.addr3, receiver, 6); + assoc_req->frame_header.seq_control.sequence_number = (rand() % 4096); + + assoc_req->fixed_parameters.capabilities_information = BYTESWAP16(LIBWIFI_DEFAULT_AP_CAPABS); + assoc_req->fixed_parameters.listen_interval = BYTESWAP16(LIBWIFI_DEFAULT_LISTEN_INTERVAL); + + libwifi_quick_add_tag(&assoc_req->tags, TAG_SSID, (const unsigned char *) ssid, strlen(ssid)); + libwifi_quick_add_tag(&assoc_req->tags, TAG_DS_PARAMETER, (const unsigned char *) &channel, 1); + + return 0; +} + +/** + * Copy a libwifi_assoc_req into a regular unsigned char buffer. This is useful when injecting generated + * libwifi frames. + */ +size_t libwifi_dump_assoc_req(struct libwifi_assoc_req *assoc_req, unsigned char *buf, size_t buf_len) { + size_t assoc_req_len = libwifi_get_assoc_req_length(assoc_req); + if (assoc_req_len > buf_len) { + return -EINVAL; + } + + size_t offset = 0; + memcpy(buf + offset, &assoc_req->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header)); + offset += sizeof(struct libwifi_mgmt_unordered_frame_header); + + memcpy(buf + offset, &assoc_req->fixed_parameters, sizeof(struct libwifi_assoc_req_fixed_parameters)); + offset += sizeof(struct libwifi_assoc_req_fixed_parameters); + + memcpy(buf + offset, assoc_req->tags.parameters, assoc_req->tags.length); + offset += assoc_req->tags.length; + + return assoc_req_len; +} + +/** + * Because the tagged parameters memory is managed inside of the library, the library must + * be the one to free it, too. + */ +void libwifi_free_assoc_req(struct libwifi_assoc_req *assoc_req) { + free(assoc_req->tags.parameters); +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_GEN_ASSOCREQUEST_H +#define LIBWIFI_GEN_ASSOCREQUEST_H + +#include "../../core/frame/frame.h" +#include "../../core/frame/management/assoc_request.h" +#include "../../core/frame/management/common.h" + +/** + * Create a new association request + * + * @param assoc_req A new libwifi_assoc_req struct + * @param receiver The receiver MAC address + * @param transmitter The transmitter MAC address + * @param ssid The desired BSS SSID + * @param channel The desired channel + * @param zero on success + */ +int libwifi_create_assoc_req(struct libwifi_assoc_req *assoc_req, const unsigned char receiver[6], + const unsigned char transmitter[6], const char *ssid, uint8_t channel); +size_t libwifi_get_assoc_req_length(struct libwifi_assoc_req *assoc_req); +size_t libwifi_dump_assoc_req(struct libwifi_assoc_req *assoc_req, unsigned char *buf, size_t buf_len); +void libwifi_free_assoc_req(struct libwifi_assoc_req *assoc_req); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "assoc_response.h" +#include "../../core/frame/tag.h" +#include "../../core/frame/tag_iterator.h" +#include "../../core/misc/byteswap.h" +#include "../../core/misc/epoch.h" +#include "../../core/misc/types.h" +#include "common.h" + +#include +#include +#include +#include +#include +#include + +/** + * The length of an association response frame is the sum of the header length, the fixed parameters length, + * and the tagged parameters length. + */ +size_t libwifi_get_assoc_resp_length(struct libwifi_assoc_resp *assoc_resp) { + return sizeof(struct libwifi_mgmt_unordered_frame_header) + + sizeof(struct libwifi_assoc_resp_fixed_parameters) + assoc_resp->tags.length; +} + +/** + * Simple helper function to set the channel of an association response by removing and re-adding the + * DS tagged parameter. + */ +void libwifi_set_assoc_resp_channel(struct libwifi_assoc_resp *assoc_resp, uint8_t channel) { + if (assoc_resp->tags.length != 0) { + libwifi_remove_tag(&assoc_resp->tags, TAG_DS_PARAMETER); + } + + const unsigned char *chan = (const unsigned char *) &channel; + + libwifi_quick_add_tag(&assoc_resp->tags, TAG_DS_PARAMETER, chan, 1); +} + +/** + * The generated association response frame is made with sane defaults defined in common.h and core/types.h. + * Two tagged parameters are also added to the association response: Channel and Supported Rates. + */ +void libwifi_create_assoc_resp(struct libwifi_assoc_resp *assoc_resp, const unsigned char receiver[6], + const unsigned char transmitter[6], uint8_t channel) { + memset(assoc_resp, 0, sizeof(struct libwifi_assoc_resp)); + + assoc_resp->frame_header.frame_control.type = TYPE_MANAGEMENT; + assoc_resp->frame_header.frame_control.subtype = SUBTYPE_ASSOC_RESP; + memcpy(&assoc_resp->frame_header.addr1, receiver, 6); + memcpy(&assoc_resp->frame_header.addr2, transmitter, 6); + + assoc_resp->fixed_parameters.capabilities_information = BYTESWAP16(LIBWIFI_DEFAULT_AP_CAPABS); + assoc_resp->fixed_parameters.status_code = STATUS_SUCCESS; + assoc_resp->fixed_parameters.association_id = rand() % 4096; + + libwifi_set_assoc_resp_channel(assoc_resp, channel); + + const unsigned char supported_rates[] = LIBWIFI_DEFAULT_SUPP_RATES; + libwifi_quick_add_tag(&assoc_resp->tags, TAG_SUPP_RATES, supported_rates, sizeof(supported_rates) - 1); +} + +/** + * Copy a libwifi_assoc_resp into a regular unsigned char buffer. This is useful when injecting generated + * libwifi frames. + */ +size_t libwifi_dump_assoc_resp(struct libwifi_assoc_resp *assoc_resp, unsigned char *buf, size_t buf_len) { + size_t assoc_resp_len = libwifi_get_assoc_resp_length(assoc_resp); + if (assoc_resp_len > buf_len) { + return -EINVAL; + } + + size_t offset = 0; + memcpy(buf + offset, &assoc_resp->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header)); + offset += sizeof(struct libwifi_mgmt_unordered_frame_header); + + memcpy(buf + offset, &assoc_resp->fixed_parameters, sizeof(struct libwifi_assoc_resp_fixed_parameters)); + offset += sizeof(struct libwifi_assoc_resp_fixed_parameters); + + memcpy(buf + offset, assoc_resp->tags.parameters, assoc_resp->tags.length); + offset += assoc_resp->tags.length; + + return assoc_resp_len; +} + +/** + * Because the tagged parameters memory is managed inside of the library, the library must + * be the one to free it, too. + */ +void libwifi_free_assoc_resp(struct libwifi_assoc_resp *assoc_resp) { + free(assoc_resp->tags.parameters); +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_GEN_ASSOCRESP_H +#define LIBWIFI_GEN_ASSOCRESP_H + +#include "../../core/frame/management/assoc_response.h" + +/** + * Set the channel of a libwifi_assoc_resp. + * + * @param assoc_resp A libwifi_assoc_resp + * @param channel The new channel + */ +void libwifi_set_assoc_resp_channel(struct libwifi_assoc_resp *assoc_resp, uint8_t channel); + +/** + * Calculate the length of a given libwifi_assoc_resp + * + * @param assoc_resp A libwifi_assoc_resp + * @return The length of the given assoc_resp + */ +size_t libwifi_get_assoc_resp_length(struct libwifi_assoc_resp *assoc_resp); + +/** + * Generate a populated libwifi assoc_resp. + * + * A generated libwifi assoc_resp can be "dumped" into a buffer for packet injection + * via the libwifi_dump_assoc_resp. + * + * @param assoc_resp A libwifi_assoc_resp + * @param receiver The receiver MAC address, aka address 1 + * @param transmitter The source MAC address, aka address 2 + * @param channel The desired channel of the assoc_resp + * + */ +void libwifi_create_assoc_resp(struct libwifi_assoc_resp *assoc_resp, const unsigned char receiver[6], + const unsigned char transmitter[6], uint8_t channel); + +/** + * Dump a libwifi_assoc_resp into a raw format for packet injection. + * + * @param assoc_resp A libwifi_assoc_resp + * @param buf The output buffer for the frame data + * @param buf_len The length of the output buffer + * @return The length of the dumped assoc_resp + */ +size_t libwifi_dump_assoc_resp(struct libwifi_assoc_resp *assoc_resp, unsigned char *buf, size_t buf_len); + +/** + * Free any memory claimed by a libwifi_assoc_resp back to the system. + * + * @param assoc_resp A libwifi_assoc_resp + */ +void libwifi_free_assoc_resp(struct libwifi_assoc_resp *assoc_resp); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "atim.h" + +#include +#include + +int libwifi_create_atim(struct libwifi_atim *atim, const unsigned char transmitter[6], + const unsigned char receiver[6], const unsigned char bssid[6]) { + memset(atim, 0, sizeof(struct libwifi_atim)); + + atim->frame_header.frame_control.type = TYPE_MANAGEMENT; + atim->frame_header.frame_control.subtype = SUBTYPE_ATIM; + memcpy(&atim->frame_header.addr1, transmitter, 6); + memcpy(&atim->frame_header.addr2, receiver, 6); + memcpy(&atim->frame_header.addr3, bssid, 6); + atim->frame_header.frame_control.flags.power_mgmt = 1; + atim->frame_header.duration = (rand() % 4096); + atim->frame_header.seq_control.sequence_number = (rand() % 4096); + + return 0; +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_GEN_ATIM_H +#define LIBWIFI_GEN_ATIM_H + +#include "../../core/frame/management/atim.h" + +int libwifi_create_atim(struct libwifi_atim *atim, const unsigned char transmitter[6], + const unsigned char receiver[6], const unsigned char bssid[6]); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "authentication.h" +#include "../../core/misc/byteswap.h" + +#include +#include +#include + +/** + * The length of an authentication frame is the sum of the header length, the fixed parameters length, and the + * tagged parameters length. + */ +size_t libwifi_get_auth_length(struct libwifi_auth *auth) { + return sizeof(struct libwifi_mgmt_unordered_frame_header) + sizeof(struct libwifi_auth_fixed_parameters) + + auth->tags.length; +} + +/** + * The generated authentication frame is made with sane defaults defined in common.h. + */ +void libwifi_create_auth(struct libwifi_auth *auth, const unsigned char receiver[6], + const unsigned char transmitter[6], uint16_t algorithm_number, + uint16_t transaction_sequence, uint16_t status_code) { + memset(auth, 0, sizeof(struct libwifi_auth)); + + auth->frame_header.frame_control.type = TYPE_MANAGEMENT; + auth->frame_header.frame_control.subtype = SUBTYPE_AUTH; + memcpy(&auth->frame_header.addr1, receiver, 6); + memcpy(&auth->frame_header.addr2, transmitter, 6); + memcpy(&auth->frame_header.addr3, transmitter, 6); + auth->frame_header.seq_control.sequence_number = (rand() % 4096); + + auth->fixed_parameters.algorithm_number = algorithm_number; + auth->fixed_parameters.transaction_sequence = transaction_sequence; + auth->fixed_parameters.status_code = status_code; +} + +/** + * Copy a libwifi_auth into a regular unsigned char buffer. This is useful when injecting generated + * libwifi frames. + */ +size_t libwifi_dump_auth(struct libwifi_auth *auth, unsigned char *buf, size_t buf_len) { + size_t auth_len = libwifi_get_auth_length(auth); + if (auth_len > buf_len) { + return -EINVAL; + } + + size_t offset = 0; + memcpy(buf + offset, &auth->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header)); + offset += sizeof(struct libwifi_mgmt_unordered_frame_header); + + memcpy(buf + offset, &auth->fixed_parameters, sizeof(struct libwifi_auth_fixed_parameters)); + offset += sizeof(struct libwifi_auth_fixed_parameters); + + memcpy(buf + offset, auth->tags.parameters, auth->tags.length); + offset += auth->tags.length; + + return auth_len; +} + +/** + * Because the tagged parameters memory is managed inside of the library, the library must + * be the one to free it, too. + */ +void libwifi_free_auth(struct libwifi_auth *auth) { + free(auth->tags.parameters); +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_GEN_AUTH_H +#define LIBWIFI_GEN_AUTH_H + +#include + +#include "../../core/frame/management/authentication.h" + +/** + * Calculate the length of a given libwifi_auth + * + * @param auth A libwifi_auth + * @return The length of the given auth + */ +size_t libwifi_get_auth_length(struct libwifi_auth *auth); + +/** + * Generate a populated libwifi auth. + * + * A generated libwifi auth can be "dumped" into a buffer for packet injection + * via the libwifi_dump_auth. + * + * @param auth A libwifi_auth + * @param receiver The receiver MAC address, aka address 1 + * @param transmitter The source MAC address, aka address 2 + * @param algorithm_number Algorithm type to use + * + */ +void libwifi_create_auth(struct libwifi_auth *auth, const unsigned char receiver[6], + const unsigned char transmitter[6], uint16_t algorithm_number, + uint16_t transaction_sequence, uint16_t status_code); + +/** + * Dump a libwifi_auth into a raw format for packet injection. + * + * @param auth A libwifi_auth + * @param buf The output buffer for the frame data + * @param buf_len The length of the output buffer + * @return The length of the dumped auth + */ +size_t libwifi_dump_auth(struct libwifi_auth *auth, unsigned char *buf, size_t buf_len); + +/** + * Free any memory claimed by a libwifi_auth back to the system. + * + * @param auth A libwifi_auth + */ +void libwifi_free_auth(struct libwifi_auth *auth); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "beacon.h" +#include "../../core/frame/tag.h" +#include "../../core/frame/tag_iterator.h" +#include "../../core/misc/byteswap.h" +#include "../../core/misc/epoch.h" +#include "common.h" + +#include +#include +#include +#include +#include +#include + +/** + * The length of a beacon frame is the sum of the header length, the fixed parameters length, and the tagged + * parameters length. + */ +size_t libwifi_get_beacon_length(struct libwifi_beacon *beacon) { + return sizeof(struct libwifi_mgmt_unordered_frame_header) + + sizeof(struct libwifi_beacon_fixed_parameters) + beacon->tags.length; +} + +/** + * Simple helper to set the beacon SSID tag by removing it and then adding it back with the new value. + */ +void libwifi_set_beacon_ssid(struct libwifi_beacon *beacon, const char *ssid) { + if (beacon->tags.length != 0) { + libwifi_remove_tag(&beacon->tags, TAG_SSID); + } + + libwifi_quick_add_tag(&beacon->tags, TAG_SSID, (void *) ssid, strlen(ssid)); +} + +/** + * Simple helper to set the beacon DS tag by removing it and then adding it back with the new value. + */ +void libwifi_set_beacon_channel(struct libwifi_beacon *beacon, uint8_t channel) { + if (beacon->tags.length != 0) { + libwifi_remove_tag(&beacon->tags, TAG_DS_PARAMETER); + } + + const unsigned char *chan = (const unsigned char *) &channel; + + libwifi_quick_add_tag(&beacon->tags, TAG_DS_PARAMETER, chan, 1); +} + +/** + * The generated beacon frame is made with sane defaults defined in common.h. + * Three tagged parameters are also added to the beacon: SSID, Channel and Supported Rates. + */ +void libwifi_create_beacon(struct libwifi_beacon *beacon, const unsigned char receiver[6], + const unsigned char transmitter[6], const char *ssid, uint8_t channel) { + memset(beacon, 0, sizeof(struct libwifi_beacon)); + + beacon->frame_header.frame_control.type = TYPE_MANAGEMENT; + beacon->frame_header.frame_control.subtype = SUBTYPE_BEACON; + memcpy(&beacon->frame_header.addr1, receiver, 6); + memcpy(&beacon->frame_header.addr2, transmitter, 6); + beacon->frame_header.seq_control.sequence_number = (rand() % 4096); + + beacon->fixed_parameters.timestamp = BYTESWAP64(libwifi_get_epoch()); + beacon->fixed_parameters.beacon_interval = BYTESWAP16(LIBWIFI_DEFAULT_BEACON_INTERVAL); + beacon->fixed_parameters.capabilities_information = BYTESWAP16(LIBWIFI_DEFAULT_AP_CAPABS); + + libwifi_set_beacon_ssid(beacon, ssid); + libwifi_set_beacon_channel(beacon, channel); + + const unsigned char supported_rates[] = LIBWIFI_DEFAULT_SUPP_RATES; + libwifi_quick_add_tag(&beacon->tags, TAG_SUPP_RATES, supported_rates, sizeof(supported_rates) - 1); +} + +/** + * Copy a libwifi_beacon into a regular unsigned char buffer. This is useful when injecting generated + * libwifi frames. + */ +size_t libwifi_dump_beacon(struct libwifi_beacon *beacon, unsigned char *buf, size_t buf_len) { + size_t beacon_len = libwifi_get_beacon_length(beacon); + if (beacon_len > buf_len) { + return -EINVAL; + } + + size_t offset = 0; + memcpy(buf + offset, &beacon->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header)); + offset += sizeof(struct libwifi_mgmt_unordered_frame_header); + + memcpy(buf + offset, &beacon->fixed_parameters, sizeof(struct libwifi_beacon_fixed_parameters)); + offset += sizeof(struct libwifi_beacon_fixed_parameters); + + memcpy(buf + offset, beacon->tags.parameters, beacon->tags.length); + offset += beacon->tags.length; + + return beacon_len; +} + +/** + * Because the tagged parameters memory is managed inside of the library, the library must + * be the one to free it, too. + */ +void libwifi_free_beacon(struct libwifi_beacon *beacon) { + free(beacon->tags.parameters); +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_GEN_BEACON_H +#define LIBWIFI_GEN_BEACON_H + +#include "../../core/frame/management/beacon.h" + +/** + * Set the SSID of a struct libwifi_beacon. + * + * @param beacon A struct libwifi_beacon + * @param ssid The new SSID + */ +void libwifi_set_beacon_ssid(struct libwifi_beacon *beacon, const char *ssid); + +/** + * Set the channel of a struct libwifi_beacon. + * + * @param beacon A struct libwifi_beacon + * @param channel The new channel + */ +void libwifi_set_beacon_channel(struct libwifi_beacon *beacon, uint8_t channel); + +/** + * Calculate the length of a given struct libwifi_beacon + * + * @param beacon A struct libwifi_beacon + * @return The length of the given beacon + */ +size_t libwifi_get_beacon_length(struct libwifi_beacon *beacon); + +/** + * Generate a populated libwifi beacon. + * + * A generated libwifi beacon can be "dumped" into a buffer for packet injection + * via the libwifi_dump_beacon. + * + * @param beacon A struct libwifi_beacon + * @param receiver The receiver MAC address, aka address 1 + * @param transmitter The source MAC address, aka address 2 + * @param ssid The SSID of the beacon. Maximum length is 32 characters + * @param channel The desired channel of the beacon + * + */ +void libwifi_create_beacon(struct libwifi_beacon *beacon, const unsigned char receiver[6], + const unsigned char transmitter[6], const char *ssid, uint8_t channel); + +/** + * Dump a struct libwifi_beacon into a raw format for packet injection. + * + * @param beacon A struct libwifi_beacon + * @param buf The output buffer for the frame data + * @param buf_len The length of the output buffer + * @return The length of the dumped beacon + */ +size_t libwifi_dump_beacon(struct libwifi_beacon *beacon, unsigned char *buf, size_t buf_len); + +/** + * Free any memory claimed by a struct libwifi_beacon back to the system. + * + * @param beacon A struct libwifi_beacon + */ +void libwifi_free_beacon(struct libwifi_beacon *beacon); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_GEN_COMMON_H +#define LIBWIFI_GEN_COMMON_H + +/** + * A sane default for an AP-side capabilities information field. + * + * 0x0001 = Transmitter is an AP + */ +#define LIBWIFI_DEFAULT_AP_CAPABS 0x0001 + +/** + * A sane default for an STA-side capabilities information field. + * + * 0x0000 = None + */ +#define LIBWIFI_DEFAULT_STA_CAPABS 0x0000 + +/** + * A sane default for the listen_interval field. + * + * 0x0001 = 1 Beacon Interval + */ +#define LIBWIFI_DEFAULT_LISTEN_INTERVAL 0x0001 + +/** + * A sane default for a beacon_interval field. + * + * 0x0064 = 0.1024 Seconds + */ +#define LIBWIFI_DEFAULT_BEACON_INTERVAL 0x0064 + +/** + * A sane default for the supported rates frame field. + * + * 1, 2, 5.5, 11, 18, 24, 36, 54 Mbit/s + */ +#define LIBWIFI_DEFAULT_SUPP_RATES "\x82\x84\x8b\x96\x24\x30\x48\x6c" + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "deauthentication.h" +#include "../../core/misc/byteswap.h" + +#include +#include +#include + +/** + * The length of a deauth frame is the sum of the header length, the fixed parameters length, and the tagged + * parameters length. + */ +size_t libwifi_get_deauth_length(struct libwifi_deauth *deauth) { + return sizeof(struct libwifi_mgmt_unordered_frame_header) + + sizeof(struct libwifi_deauth_fixed_parameters) + deauth->tags.length; +} + +/** + * The generated deauthentication frame contains only the supplied receiver, transmitter and reason_code by + * default. + */ +int libwifi_create_deauth(struct libwifi_deauth *deauth, const unsigned char receiver[6], + const unsigned char transmitter[6], uint16_t reason_code) { + memset(deauth, 0, sizeof(struct libwifi_deauth)); + + deauth->frame_header.frame_control.type = TYPE_MANAGEMENT; + deauth->frame_header.frame_control.subtype = SUBTYPE_DEAUTH; + memcpy(&deauth->frame_header.addr1, receiver, 6); + memcpy(&deauth->frame_header.addr2, transmitter, 6); + memcpy(&deauth->frame_header.addr3, transmitter, 6); + + deauth->frame_header.seq_control.sequence_number = (rand() % 4096); + + memcpy(&deauth->fixed_parameters.reason_code, &reason_code, sizeof(reason_code)); + + return 0; +} + +/** + * Copy a libwifi_deauth into a regular unsigned char buffer. This is useful when injecting generated + * libwifi frames. + */ +size_t libwifi_dump_deauth(struct libwifi_deauth *deauth, unsigned char *buf, size_t buf_len) { + size_t deauth_len = libwifi_get_deauth_length(deauth); + if (deauth_len > buf_len) { + return -EINVAL; + } + + size_t offset = 0; + memcpy(buf + offset, &deauth->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header)); + offset += sizeof(struct libwifi_mgmt_unordered_frame_header); + + memcpy(buf + offset, &deauth->fixed_parameters, sizeof(struct libwifi_deauth_fixed_parameters)); + offset += sizeof(struct libwifi_deauth_fixed_parameters); + + memcpy(buf + offset, deauth->tags.parameters, deauth->tags.length); + offset += deauth->tags.length; + + return deauth_len; +} + +/** + * Because the tagged parameters memory is managed inside of the library, the library must + * be the one to free it, too. + */ +void libwifi_free_deauth(struct libwifi_deauth *deauth) { + free(deauth->tags.parameters); +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_GEN_DEAUTH_H +#define LIBWIFI_GEN_DEAUTH_H + +#include + +#include "../../core/frame/management/deauthentication.h" + +/** + * Calculate the length of a given libwifi_deauth + * + * @param deauth A libwifi_deauth + * @return The length of the given deauth + */ +size_t libwifi_get_deauth_length(struct libwifi_deauth *deauth); + +/** + * Generate a populated libwifi deauth. + * + * A generated libwifi deauth can be "dumped" into a buffer for packet injection + * via the libwifi_dump_deauth. + * + * @param deauth A libwifi_deauth + * @param receiver The receiver MAC address, aka address 1 + * @param transmitter The source MAC address, aka address 2 + * @param reason_code The deauth reason code + * + */ +int libwifi_create_deauth(struct libwifi_deauth *deauth, const unsigned char receiver[6], + const unsigned char transmitter[6], uint16_t reason_code); + +/** + * Dump a libwifi_deauth into a raw format for packet injection. + * + * @param deauth A libwifi_deauth + * @param buf The output buffer for the frame data + * @param buf_len The length of the output buffer + * @return The length of the dumped deauth + */ +size_t libwifi_dump_deauth(struct libwifi_deauth *deauth, unsigned char *buf, size_t buf_len); + +/** + * Free any memory claimed by a libwifi_deauth back to the system. + * + * @param deauth A libwifi_deauth + */ +void libwifi_free_deauth(struct libwifi_deauth *deauth); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "disassociation.h" +#include "../../core/misc/byteswap.h" + +#include +#include +#include + +/** + * The length of a disassoc frame is the sum of the header length, the fixed parameters length, and the tagged + * parameters length. + */ +size_t libwifi_get_disassoc_length(struct libwifi_disassoc *disassoc) { + return sizeof(struct libwifi_mgmt_unordered_frame_header) + + sizeof(struct libwifi_disassoc_fixed_parameters) + disassoc->tags.length; +} + +/** + * The generated disassociation frame contains only the supplied receiver, transmitter and reason_code by + * default. + */ +void libwifi_create_disassoc(struct libwifi_disassoc *disassoc, const unsigned char receiver[6], + const unsigned char transmitter[6], uint16_t reason_code) { + memset(disassoc, 0, sizeof(struct libwifi_disassoc)); + + disassoc->frame_header.frame_control.type = TYPE_MANAGEMENT; + disassoc->frame_header.frame_control.subtype = SUBTYPE_DISASSOC; + memcpy(&disassoc->frame_header.addr1, receiver, 6); + memcpy(&disassoc->frame_header.addr2, transmitter, 6); + memcpy(&disassoc->frame_header.addr3, transmitter, 6); + + disassoc->frame_header.seq_control.sequence_number = (rand() % 4096); + + memcpy(&disassoc->fixed_parameters.reason_code, &reason_code, sizeof(reason_code)); +} + +/** + * Copy a libwifi_disassoc into a regular unsigned char buffer. This is useful when injecting generated + * libwifi frames. + */ +size_t libwifi_dump_disassoc(struct libwifi_disassoc *disassoc, unsigned char *buf, size_t buf_len) { + size_t disassoc_len = libwifi_get_disassoc_length(disassoc); + if (disassoc_len > buf_len) { + return -EINVAL; + } + + size_t offset = 0; + memcpy(buf + offset, &disassoc->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header)); + offset += sizeof(struct libwifi_mgmt_unordered_frame_header); + + memcpy(buf + offset, &disassoc->fixed_parameters, sizeof(struct libwifi_disassoc_fixed_parameters)); + offset += sizeof(struct libwifi_disassoc_fixed_parameters); + + memcpy(buf + offset, disassoc->tags.parameters, disassoc->tags.length); + offset += disassoc->tags.length; + + return disassoc_len; +} + +/** + * Because the tagged parameters memory is managed inside of the library, the library must + * be the one to free it, too. + */ +void libwifi_free_disassoc(struct libwifi_disassoc *disassoc) { + free(disassoc->tags.parameters); +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_GEN_DISASSOC_H +#define LIBWIFI_GEN_DISASSOC_H + +#include + +#include "../../core/frame/management/disassociation.h" + +/** + * Calculate the length of a given libwifi_disassoc + * + * @param disassoc A libwifi_disassoc + * @return The length of the given disassoc + */ +size_t libwifi_get_disassoc_length(struct libwifi_disassoc *disassoc); + +/** + * Generate a populated libwifi disassoc. + * + * A generated libwifi disassoc can be "dumped" into a buffer for packet injection + * via the libwifi_dump_disassoc. + * + * @param disassoc A libwifi_disassoc + * @param receiver The receiver MAC address, aka address 1 + * @param transmitter The source MAC address, aka address 2 + * @param reason_code The disassoc reason code + * + */ +void libwifi_create_disassoc(struct libwifi_disassoc *disassoc, const unsigned char receiver[6], + const unsigned char transmitter[6], uint16_t reason_code); + +/** + * Dump a libwifi_disassoc into a raw format for packet injection. + * + * @param disassoc A libwifi_disassoc + * @param buf The output buffer for the frame data + * @param buf_len The length of the output buffer + * @return The length of the dumped disassoc + */ +size_t libwifi_dump_disassoc(struct libwifi_disassoc *disassoc, unsigned char *buf, size_t buf_len); + +/** + * Free any memory claimed by a libwifi_disassoc back to the system. + * + * @param disassoc A libwifi_disassoc + */ +void libwifi_free_disassoc(struct libwifi_disassoc *disassoc); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "probe_request.h" +#include "../../core/misc/byteswap.h" + +#include +#include +#include + +/** + * The length of a probe request frame is the sum of the header length plus the tagged parameters length. + */ +size_t libwifi_get_probe_req_length(struct libwifi_probe_req *probe_req) { + return sizeof(struct libwifi_mgmt_unordered_frame_header) + probe_req->tags.length; +} + +/** + * The generated probe request frame is made with sane defaults defined in common.h. + * Two tagged parameters are also added to the beacon: SSID and Channel. + */ +void libwifi_create_probe_req(struct libwifi_probe_req *probe_req, const unsigned char receiver[6], + const unsigned char transmitter[6], const unsigned char bssid[6], + const char *ssid, uint8_t channel) { + memset(probe_req, 0, sizeof(struct libwifi_probe_req)); + + probe_req->frame_header.frame_control.type = TYPE_MANAGEMENT; + probe_req->frame_header.frame_control.subtype = SUBTYPE_PROBE_REQ; + memcpy(&probe_req->frame_header.addr1, receiver, 6); + memcpy(&probe_req->frame_header.addr2, transmitter, 6); + memcpy(&probe_req->frame_header.addr3, bssid, 6); + probe_req->frame_header.seq_control.sequence_number = (rand() % 4096); + + libwifi_quick_add_tag(&probe_req->tags, TAG_SSID, (const unsigned char *) ssid, strlen(ssid)); + libwifi_quick_add_tag(&probe_req->tags, TAG_DS_PARAMETER, (const unsigned char *) &channel, 1); +} + +/** + * Copy a libwifi_probe_req into a regular unsigned char buffer. This is useful when injecting generated + * libwifi frames. + */ +size_t libwifi_dump_probe_req(struct libwifi_probe_req *probe_req, unsigned char *buf, size_t buf_len) { + size_t probe_req_len = libwifi_get_probe_req_length(probe_req); + if (probe_req_len > buf_len) { + return -EINVAL; + } + + size_t offset = 0; + memcpy(buf + offset, &probe_req->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header)); + offset += sizeof(struct libwifi_mgmt_unordered_frame_header); + + memcpy(buf + offset, probe_req->tags.parameters, probe_req->tags.length); + offset += probe_req->tags.length; + + return probe_req_len; +} + +/** + * Because the tagged parameters memory is managed inside of the library, the library must + * be the one to free it, too. + */ +void libwifi_free_probe_req(struct libwifi_probe_req *probe_req) { + free(probe_req->tags.parameters); +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_GEN_PROBEREQ_H +#define LIBWIFI_GEN_PROBEREQ_H + +#include + +#include "../../core/frame/management/probe_request.h" + +/** + * Calculate the length of a given libwifi_probe_req + * + * @param probe_req A libwifi_probe_req + * @return The length of the given probe_req + */ +size_t libwifi_get_probe_req_length(struct libwifi_probe_req *probe_req); + +/** + * Generate a populated libwifi probe_req. + * + * A generated libwifi probe_req can be "dumped" into a buffer for packet injection + * via the libwifi_dump_probe_req. + * + * @param probe_req A libwifi_probe_req + * @param receiver The receiver MAC address, aka address 1 + * @param transmitter The source MAC address, aka address 2 + * @param reason_code The probe_req reason code + * + */ +void libwifi_create_probe_req(struct libwifi_probe_req *probe_req, const unsigned char receiver[6], + const unsigned char transmitter[6], const unsigned char bssid[6], + const char *ssid, uint8_t channel); + +/** + * Dump a libwifi_probe_req into a raw format for packet injection. + * + * @param probe_req A libwifi_probe_req + * @param buf The output buffer for the frame data + * @param buf_len The length of the output buffer + * @return The length of the dumped probe_req + */ +size_t libwifi_dump_probe_req(struct libwifi_probe_req *probe_req, unsigned char *buf, size_t buf_len); + +/** + * Free any memory claimed by a libwifi_probe_req back to the system. + * + * @param probe_req A libwifi_probe_req + */ +void libwifi_free_probe_req(struct libwifi_probe_req *probe_req); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "probe_response.h" +#include "../../core/frame/tag.h" +#include "../../core/frame/tag_iterator.h" +#include "../../core/misc/byteswap.h" +#include "../../core/misc/epoch.h" +#include "common.h" + +#include +#include +#include +#include +#include +#include + +/** + * The length of a probe response frame is the sum of the header length, the fixed parameters length, and the + * tagged parameters length. + */ +size_t libwifi_get_probe_resp_length(struct libwifi_probe_resp *probe_resp) { + return sizeof(struct libwifi_mgmt_unordered_frame_header) + + sizeof(struct libwifi_probe_resp_fixed_parameters) + probe_resp->tags.length; +} + +/** + * Simple helper to set the probe response SSID tag by removing it and then adding it back with the new value. + */ +void libwifi_set_probe_resp_ssid(struct libwifi_probe_resp *probe_resp, const char *ssid) { + if (probe_resp->tags.length != 0) { + libwifi_remove_tag(&probe_resp->tags, TAG_SSID); + } + + libwifi_quick_add_tag(&probe_resp->tags, TAG_SSID, (void *) ssid, strlen(ssid)); +} + +/** + * Simple helper to set the probe response DS tag by removing it and then adding it back with the new value. + */ +void libwifi_set_probe_resp_channel(struct libwifi_probe_resp *probe_resp, uint8_t channel) { + if (probe_resp->tags.length != 0) { + libwifi_remove_tag(&probe_resp->tags, TAG_DS_PARAMETER); + } + + const unsigned char *chan = (const unsigned char *) &channel; + + libwifi_quick_add_tag(&probe_resp->tags, TAG_DS_PARAMETER, chan, 1); +} + +/** + * The generated probe response frame is made with sane defaults defined in common.h. + * Three tagged parameters are also added to the probe response: SSID, Channel and Supported Rates. + */ +void libwifi_create_probe_resp(struct libwifi_probe_resp *probe_resp, const unsigned char receiver[6], + const unsigned char transmitter[6], const char *ssid, uint8_t channel) { + memset(probe_resp, 0, sizeof(struct libwifi_probe_resp)); + + probe_resp->frame_header.frame_control.type = TYPE_MANAGEMENT; + probe_resp->frame_header.frame_control.subtype = SUBTYPE_PROBE_RESP; + memcpy(&probe_resp->frame_header.addr1, receiver, 6); + memcpy(&probe_resp->frame_header.addr2, transmitter, 6); + + probe_resp->frame_header.seq_control.sequence_number = (rand() % 4096); + probe_resp->fixed_parameters.timestamp = BYTESWAP64(libwifi_get_epoch()); + uint16_t probe_resp_interval = 50 + (rand() % 100); + probe_resp->fixed_parameters.probe_resp_interval = BYTESWAP16(probe_resp_interval); + probe_resp->fixed_parameters.capabilities_information = BYTESWAP16(LIBWIFI_DEFAULT_AP_CAPABS); + + libwifi_set_probe_resp_ssid(probe_resp, ssid); + libwifi_set_probe_resp_channel(probe_resp, channel); + + const unsigned char supported_rates[] = LIBWIFI_DEFAULT_SUPP_RATES; + libwifi_quick_add_tag(&probe_resp->tags, TAG_SUPP_RATES, supported_rates, sizeof(supported_rates) - 1); +} + +/** + * Copy a libwifi_probe_resp into a regular unsigned char buffer. This is useful when injecting generated + * libwifi frames. + */ +size_t libwifi_dump_probe_resp(struct libwifi_probe_resp *probe_resp, unsigned char *buf, size_t buf_len) { + size_t probe_resp_len = libwifi_get_probe_resp_length(probe_resp); + if (probe_resp_len > buf_len) { + return -EINVAL; + } + + size_t offset = 0; + memcpy(buf + offset, &probe_resp->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header)); + offset += sizeof(struct libwifi_mgmt_unordered_frame_header); + + memcpy(buf + offset, &probe_resp->fixed_parameters, sizeof(struct libwifi_probe_resp_fixed_parameters)); + offset += sizeof(struct libwifi_probe_resp_fixed_parameters); + + memcpy(buf + offset, probe_resp->tags.parameters, probe_resp->tags.length); + offset += probe_resp->tags.length; + + return probe_resp_len; +} + +/** + * Because the tagged parameters memory is managed inside of the library, the library must + * be the one to free it, too. + */ +void libwifi_free_probe_resp(struct libwifi_probe_resp *probe_resp) { + free(probe_resp->tags.parameters); +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_GEN_PROBERESP_H +#define LIBWIFI_GEN_PROBERESP_H + +#include "../../core/frame/management/probe_response.h" + +/** + * Set the SSID of a libwifi_probe_resp. + * + * @param probe_resp A libwifi_probe_resp + * @param ssid The new SSID + */ +void libwifi_set_probe_resp_ssid(struct libwifi_probe_resp *probe_resp, const char *ssid); + +/** + * Set the channel of a libwifi_probe_resp. + * + * @param probe_resp A libwifi_probe_resp + * @param channel The new channel + */ +void libwifi_set_probe_resp_channel(struct libwifi_probe_resp *probe_resp, uint8_t channel); + +/** + * Calculate the length of a given libwifi_probe_resp + * + * @param probe_resp A libwifi_probe_resp + * @return The length of the given probe_resp + */ +size_t libwifi_get_probe_resp_length(struct libwifi_probe_resp *probe_resp); + +/** + * Generate a populated libwifi probe_resp. + * + * A generated libwifi probe_resp can be "dumped" into a buffer for packet injection + * via the libwifi_dump_probe_resp. + * + * @param probe_resp A libwifi_probe_resp + * @param receiver The receiver MAC address, aka address 1 + * @param transmitter The source MAC address, aka address 2 + * @param ssid The SSID of the probe_resp. Maximum length is 32 characters + * @param channel The desired channel of the probe_resp + * + */ +void libwifi_create_probe_resp(struct libwifi_probe_resp *probe_resp, const unsigned char receiver[6], + const unsigned char transmitter[6], const char *ssid, uint8_t channel); + +/** + * Dump a libwifi_probe_resp into a raw format for packet injection. + * + * @param probe_resp A libwifi_probe_resp + * @param buf The output buffer for the frame data + * @param buf_len The length of the output buffer + * @return The length of the dumped probe_resp + */ +size_t libwifi_dump_probe_resp(struct libwifi_probe_resp *probe_resp, unsigned char *buf, size_t buf_len); + +/** + * Free any memory claimed by a libwifi_probe_resp back to the system. + * + * @param probe_resp A libwifi_probe_resp + */ +void libwifi_free_probe_resp(struct libwifi_probe_resp *probe_resp); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "reassoc_request.h" +#include "common.h" + +#include +#include +#include + +/** + * The length of a reassociation request frame is the sum of the header length, the fixed parameters length, + * and the tagged parameters length. + */ +size_t libwifi_get_reassoc_req_length(struct libwifi_reassoc_req *reassoc_req) { + return sizeof(struct libwifi_mgmt_unordered_frame_header) + + sizeof(struct libwifi_reassoc_req_fixed_parameters) + reassoc_req->tags.length; +} + +/** + * The generated reassociation request frame is made with sane defaults defined in common.h. + * Two tagged parameters are also added to the reassociation frame: SSID and Channel + */ +int libwifi_create_reassoc_req(struct libwifi_reassoc_req *reassoc_req, const unsigned char receiver[6], + const unsigned char transmitter[6], const unsigned char current_ap[6], + const char *ssid, uint8_t channel) { + memset(reassoc_req, 0, sizeof(struct libwifi_reassoc_req)); + + reassoc_req->frame_header.frame_control.type = TYPE_MANAGEMENT; + reassoc_req->frame_header.frame_control.subtype = SUBTYPE_REASSOC_REQ; + memcpy(&reassoc_req->frame_header.addr1, receiver, 6); + memcpy(&reassoc_req->frame_header.addr2, transmitter, 6); + memcpy(&reassoc_req->frame_header.addr3, receiver, 6); + reassoc_req->frame_header.seq_control.sequence_number = (rand() % 4096); + + reassoc_req->fixed_parameters.capabilities_information = BYTESWAP16(LIBWIFI_DEFAULT_AP_CAPABS); + reassoc_req->fixed_parameters.listen_interval = BYTESWAP16(LIBWIFI_DEFAULT_LISTEN_INTERVAL); + memcpy(&reassoc_req->fixed_parameters.current_ap_address, current_ap, 6); + + libwifi_quick_add_tag(&reassoc_req->tags, TAG_SSID, (const unsigned char *) ssid, strlen(ssid)); + libwifi_quick_add_tag(&reassoc_req->tags, TAG_DS_PARAMETER, (const unsigned char *) &channel, 1); + + return 0; +} + +/** + * Copy a libwifi_reassoc_req into a regular unsigned char buffer. This is useful when injecting generated + * libwifi frames. + */ +size_t libwifi_dump_reassoc_req(struct libwifi_reassoc_req *reassoc_req, unsigned char *buf, size_t buf_len) { + size_t reassoc_req_len = libwifi_get_reassoc_req_length(reassoc_req); + if (reassoc_req_len > buf_len) { + return -EINVAL; + } + + size_t offset = 0; + memcpy(buf + offset, &reassoc_req->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header)); + offset += sizeof(struct libwifi_mgmt_unordered_frame_header); + + memcpy(buf + offset, &reassoc_req->fixed_parameters, sizeof(struct libwifi_reassoc_req_fixed_parameters)); + offset += sizeof(struct libwifi_reassoc_req_fixed_parameters); + + memcpy(buf + offset, reassoc_req->tags.parameters, reassoc_req->tags.length); + offset += reassoc_req->tags.length; + + return reassoc_req_len; +} + +/** + * Because the tagged parameters memory is managed inside of the library, the library must + * be the one to free it, too. + */ +void libwifi_free_reassoc_req(struct libwifi_reassoc_req *reassoc_req) { + free(reassoc_req->tags.parameters); +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_GEN_REASSOCREQUEST_H +#define LIBWIFI_GEN_REASSOCREQUEST_H + +#include "../../core/frame/frame.h" +#include "../../core/frame/management/common.h" +#include "../../core/frame/management/reassoc_request.h" + +int libwifi_create_reassoc_req(struct libwifi_reassoc_req *reassoc_req, const unsigned char receiver[6], + const unsigned char transmitter[6], const unsigned char current_ap[6], + const char *ssid, uint8_t channel); +size_t libwifi_get_reassoc_req_length(struct libwifi_reassoc_req *reassoc_req); +size_t libwifi_dump_reassoc_req(struct libwifi_reassoc_req *reassoc_req, unsigned char *buf, size_t buf_len); +void libwifi_free_reassoc_req(struct libwifi_reassoc_req *reassoc_req); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "reassoc_response.h" +#include "../../core/frame/tag.h" +#include "../../core/frame/tag_iterator.h" +#include "../../core/misc/byteswap.h" +#include "../../core/misc/epoch.h" +#include "../../core/misc/types.h" +#include "common.h" + +#include +#include +#include +#include +#include +#include + +/** + * The length of a reassociation response frame is the sum of the header length, the fixed parameters length, + * and the tagged parameters length. + */ +size_t libwifi_get_reassoc_resp_length(struct libwifi_reassoc_resp *reassoc_resp) { + return sizeof(struct libwifi_mgmt_unordered_frame_header) + + sizeof(struct libwifi_reassoc_resp_fixed_parameters) + reassoc_resp->tags.length; +} + +/** + * Simple helper to set the reassociation response DS tag by removing it and then adding it back with the new + * value. + */ +void libwifi_set_reassoc_resp_channel(struct libwifi_reassoc_resp *reassoc_resp, uint8_t channel) { + if (reassoc_resp->tags.length != 0) { + libwifi_remove_tag(&reassoc_resp->tags, TAG_DS_PARAMETER); + } + + const unsigned char *chan = (const unsigned char *) &channel; + + libwifi_quick_add_tag(&reassoc_resp->tags, TAG_DS_PARAMETER, chan, 1); +} + +/** + * The generated reassoc_resp frame is made with sane defaults defined in common.h. + * Three tagged parameters are also added to the reassoc_resp: SSID, Channel and Supported Rates. + */ +void libwifi_create_reassoc_resp(struct libwifi_reassoc_resp *reassoc_resp, const unsigned char receiver[6], + const unsigned char transmitter[6], uint8_t channel) { + memset(reassoc_resp, 0, sizeof(struct libwifi_reassoc_resp)); + + reassoc_resp->frame_header.frame_control.type = TYPE_MANAGEMENT; + reassoc_resp->frame_header.frame_control.subtype = SUBTYPE_REASSOC_RESP; + memcpy(&reassoc_resp->frame_header.addr1, receiver, 6); + memcpy(&reassoc_resp->frame_header.addr2, transmitter, 6); + + reassoc_resp->fixed_parameters.capabilities_information = BYTESWAP16(LIBWIFI_DEFAULT_AP_CAPABS); + reassoc_resp->fixed_parameters.status_code = STATUS_SUCCESS; + reassoc_resp->fixed_parameters.association_id = rand() % 4096; + + libwifi_set_reassoc_resp_channel(reassoc_resp, channel); + + const unsigned char supported_rates[] = LIBWIFI_DEFAULT_SUPP_RATES; + libwifi_quick_add_tag(&reassoc_resp->tags, TAG_SUPP_RATES, supported_rates, sizeof(supported_rates) - 1); +} + +/** + * Copy a libwifi_reassoc_resp into a regular unsigned char buffer. This is useful when injecting generated + * libwifi frames. + */ +size_t libwifi_dump_reassoc_resp(struct libwifi_reassoc_resp *reassoc_resp, unsigned char *buf, + size_t buf_len) { + size_t reassoc_resp_len = libwifi_get_reassoc_resp_length(reassoc_resp); + if (reassoc_resp_len > buf_len) { + return -EINVAL; + } + + size_t offset = 0; + memcpy(buf + offset, &reassoc_resp->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header)); + offset += sizeof(struct libwifi_mgmt_unordered_frame_header); + + memcpy(buf + offset, &reassoc_resp->fixed_parameters, + sizeof(struct libwifi_reassoc_resp_fixed_parameters)); + offset += sizeof(struct libwifi_reassoc_resp_fixed_parameters); + + memcpy(buf + offset, reassoc_resp->tags.parameters, reassoc_resp->tags.length); + offset += reassoc_resp->tags.length; + + return reassoc_resp_len; +} + +/** + * Because the tagged parameters memory is managed inside of the library, the library must + * be the one to free it, too. + */ +void libwifi_free_reassoc_resp(struct libwifi_reassoc_resp *reassoc_resp) { + free(reassoc_resp->tags.parameters); +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_GEN_REASSOCRESP_H +#define LIBWIFI_GEN_REASSOCRESP_H + +#include "../../core/frame/management/reassoc_response.h" + +/** + * Set the channel of a libwifi_reassoc_resp. + * + * @param reassoc_resp A libwifi_reassoc_resp + * @param channel The new channel + */ +void libwifi_set_reassoc_resp_channel(struct libwifi_reassoc_resp *reassoc_resp, uint8_t channel); + +/** + * Calculate the length of a given libwifi_reassoc_resp + * + * @param reassoc_resp A libwifi_reassoc_resp + * @return The length of the given reassoc_resp + */ +size_t libwifi_get_reassoc_resp_length(struct libwifi_reassoc_resp *reassoc_resp); + +/** + * Generate a populated libwifi reassoc_resp. + * + * A generated libwifi reassoc_resp can be "dumped" into a buffer for packet injection + * via the libwifi_dump_reassoc_resp. + * + * @param reassoc_resp A libwifi_reassoc_resp + * @param receiver The receiver MAC address, aka address 1 + * @param transmitter The source MAC address, aka address 2 + * @param channel The desired channel of the reassoc_resp + * + */ +void libwifi_create_reassoc_resp(struct libwifi_reassoc_resp *reassoc_resp, const unsigned char receiver[6], + const unsigned char transmitter[6], uint8_t channel); + +/** + * Dump a libwifi_reassoc_resp into a raw format for packet injection. + * + * @param reassoc_resp A libwifi_reassoc_resp + * @param buf The output buffer for the frame data + * @param buf_len The length of the output buffer + * @return The length of the dumped reassoc_resp + */ +size_t libwifi_dump_reassoc_resp(struct libwifi_reassoc_resp *reassoc_resp, unsigned char *buf, + size_t buf_len); + +/** + * Free any memory claimed by a libwifi_reassoc_resp back to the system. + * + * @param reassoc_resp A libwifi_reassoc_resp + */ +void libwifi_free_reassoc_resp(struct libwifi_reassoc_resp *reassoc_resp); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" +#include "timing_ad.h" +#include "../../core/frame/management/timing_ad.h" +#include "../../core/misc/epoch.h" +#include "../../core/frame/tag.h" + +#include +#include + +void libwifi_create_timing_advert(struct libwifi_timing_advert *adv, const unsigned char destination[6], + const unsigned char transmitter[6], struct libwifi_timing_advert_fields *adv_fields, + const char country[3], uint16_t max_reg_power, uint8_t max_tx_power, uint8_t tx_power_used, + uint8_t noise_floor) { + memset(adv, 0, sizeof(struct libwifi_timing_advert)); + + adv->frame_header.frame_control.type = TYPE_MANAGEMENT; + adv->frame_header.frame_control.subtype = SUBTYPE_TIME_ADV; + memcpy(&adv->frame_header.addr1, destination, 6); + memcpy(&adv->frame_header.addr2, transmitter, 6); + adv->frame_header.seq_control.sequence_number = (rand() % 4096); + + adv->fixed_parameters.timestamp = BYTESWAP64(libwifi_get_epoch()); + adv->fixed_parameters.measurement_pilot_interval = LIBWIFI_DEFAULT_BEACON_INTERVAL; + adv->fixed_parameters.beacon_interval = LIBWIFI_DEFAULT_BEACON_INTERVAL; + adv->fixed_parameters.capabilities_information = BYTESWAP16(LIBWIFI_DEFAULT_AP_CAPABS); + memcpy(adv->fixed_parameters.country, country, sizeof(adv->fixed_parameters.country)); + adv->fixed_parameters.max_reg_power = BYTESWAP16(max_reg_power); + adv->fixed_parameters.max_tx_power = max_tx_power; + adv->fixed_parameters.tx_power_used = tx_power_used; + adv->fixed_parameters.noise_floor = noise_floor; + + if (adv_fields == NULL) { + return; + } + + // Maximum element size is 17 + unsigned char element_data[17] = {0}; + size_t element_data_len = 0; + int offset = 0; + + memcpy(element_data, &adv_fields->timing_capabilities, sizeof(adv_fields->timing_capabilities)); + offset += sizeof(adv_fields->timing_capabilities); + + switch (adv_fields->timing_capabilities) { + case 1: { /* Time Value and Time Error fields present */ + memcpy(element_data + offset, &adv_fields->time_value, sizeof(adv_fields->time_value)); + offset += sizeof(adv_fields->time_value); + memcpy(element_data + offset, &adv_fields->time_error, sizeof(adv_fields->time_error)); + offset += sizeof(adv_fields->time_error); + break; + } + case 2: { /* Time Value, Time Error, and Time Update fields present */ + memcpy(element_data + offset, &adv_fields->time_value, sizeof(adv_fields->time_value)); + offset += sizeof(adv_fields->time_value); + memcpy(element_data + offset, &adv_fields->time_error, sizeof(adv_fields->time_error)); + offset += sizeof(adv_fields->time_error); + memcpy(element_data + offset, &adv_fields->time_update, sizeof(adv_fields->time_update)); + offset += sizeof(adv_fields->time_update); + } + default: + break; + } + + element_data_len = offset; + + libwifi_quick_add_tag(&adv->tags, TAG_TIME_ADVERTISEMENT, element_data, element_data_len); +} + +size_t libwifi_get_timing_advert_length(struct libwifi_timing_advert *adv) { + return sizeof(struct libwifi_mgmt_unordered_frame_header) + + sizeof(struct libwifi_timing_advert_fixed_params) + + adv->tags.length; +} + +size_t libwifi_dump_timing_advert(struct libwifi_timing_advert *adv, unsigned char *buf, size_t buf_len) { + size_t adv_len = libwifi_get_timing_advert_length(adv); + if (adv_len > buf_len) { + return -1; + } + + size_t offset = 0; + memcpy(buf + offset, &adv->frame_header, sizeof(struct libwifi_mgmt_unordered_frame_header)); + offset += sizeof(struct libwifi_mgmt_unordered_frame_header); + + memcpy(buf + offset, &adv->fixed_parameters, sizeof(struct libwifi_timing_advert_fixed_params)); + offset += sizeof(struct libwifi_timing_advert_fixed_params); + + memcpy(buf + offset, adv->tags.parameters, adv->tags.length); + offset += adv->tags.length; + + return adv_len; +} + +void libwifi_free_timing_advert(struct libwifi_timing_advert *adv) { + free(adv->tags.parameters); +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_GEN_TIMINGAD_H +#define LIBWIFI_GEN_TIMINGAD_H + +#include "../../core/frame/management/timing_ad.h" + +void libwifi_create_timing_advert(struct libwifi_timing_advert *adv, const unsigned char destination[6], + const unsigned char transmitter[6], struct libwifi_timing_advert_fields *adv_fields, + const char country[3], uint16_t max_reg_power, uint8_t max_tx_power, uint8_t tx_power_used, + uint8_t noise_floor); + +size_t libwifi_get_timing_advert_length(struct libwifi_timing_advert *adv); + +size_t libwifi_dump_timing_advert(struct libwifi_timing_advert *adv, unsigned char *buf, size_t buf_len); + +void libwifi_free_timing_advert(struct libwifi_timing_advert *adv); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "radiotap.h" +#include "../../core/radiotap/radiotap.h" +#include "../../core/radiotap/radiotap_iter.h" + +#include +#include +#include + +#define LIBWIFI_RADIOTAP_HEADER_LEN 8 + +size_t libwifi_create_radiotap(struct libwifi_radiotap_info *info, char *radiotap_header) { + struct ieee80211_radiotap_header rtap_hdr = {0}; + rtap_hdr.it_version = 0; + rtap_hdr.it_pad = 0; + rtap_hdr.it_present = info->present; + rtap_hdr.it_len = sizeof(struct ieee80211_radiotap_header); + + char rtap_data[LIBWIFI_MAX_RADIOTAP_LEN - LIBWIFI_RADIOTAP_HEADER_LEN] = {0}; + int offset = 0; + + uint32_t presence_bit = rtap_hdr.it_present; + for (int field = 0; field < radiotap_ns.n_bits; field++) { + if (presence_bit & 1) { + switch (field) { + case IEEE80211_RADIOTAP_CHANNEL: + memcpy(rtap_data + offset, &info->channel.freq, sizeof(info->channel.freq)); + offset += sizeof(info->channel.freq); + memcpy(rtap_data + offset, &info->channel.flags, sizeof(info->channel.flags)); + offset += sizeof(info->channel.flags); + break; + case IEEE80211_RADIOTAP_RATE: + memcpy(rtap_data + offset, &info->rate_raw, sizeof(info->rate_raw)); + offset += sizeof(info->rate_raw); + break; + case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: + memcpy(rtap_data + offset, &info->signal, sizeof(info->signal)); + offset += sizeof(info->signal); + break; + case IEEE80211_RADIOTAP_ANTENNA: + for (int i = 0; i < info->antenna_count; i++) { + memcpy(rtap_data + offset, &info->antennas->antenna_number, + sizeof(info->antennas->antenna_number)); + offset += sizeof(info->antennas->antenna_number); + memcpy(rtap_data + offset, &info->antennas->signal, sizeof(info->antennas->signal)); + offset += sizeof(info->antennas->signal); + } + break; + case IEEE80211_RADIOTAP_DBM_ANTNOISE: + break; + case IEEE80211_RADIOTAP_FLAGS: + memcpy(rtap_data + offset, &info->flags, sizeof(info->flags)); + offset += sizeof(info->flags); + break; + case IEEE80211_RADIOTAP_EXT: + memcpy(rtap_data + offset, &info->extended_flags, sizeof(info->extended_flags)); + offset += sizeof(info->extended_flags); + break; + case IEEE80211_RADIOTAP_RX_FLAGS: + memcpy(rtap_data + offset, &info->rx_flags, sizeof(info->rx_flags)); + offset += sizeof(info->rx_flags); + break; + case IEEE80211_RADIOTAP_TX_FLAGS: + memcpy(rtap_data + offset, &info->tx_flags, sizeof(info->tx_flags)); + offset += sizeof(info->tx_flags); + break; + case IEEE80211_RADIOTAP_MCS: + memcpy(rtap_data + offset, &info->mcs.known, sizeof(info->mcs.known)); + offset += sizeof(info->mcs.known); + memcpy(rtap_data + offset, &info->mcs.flags, sizeof(info->mcs.flags)); + offset += sizeof(info->mcs.flags); + memcpy(rtap_data + offset, &info->mcs.mcs, sizeof(info->mcs.mcs)); + offset += sizeof(info->mcs.mcs); + break; + case IEEE80211_RADIOTAP_DBM_TX_POWER: + memcpy(rtap_data + offset, &info->tx_power, sizeof(info->tx_power)); + offset += sizeof(info->tx_power); + break; + case IEEE80211_RADIOTAP_TIMESTAMP: + memcpy(rtap_data + offset, &info->timestamp.timestamp, sizeof(info->timestamp.timestamp)); + offset += sizeof(info->timestamp.timestamp); + memcpy(rtap_data + offset, &info->timestamp.accuracy, sizeof(info->timestamp.accuracy)); + offset += sizeof(info->timestamp.accuracy); + memcpy(rtap_data + offset, &info->timestamp.unit, sizeof(info->timestamp.unit)); + offset += sizeof(info->timestamp.unit); + memcpy(rtap_data + offset, &info->timestamp.flags, sizeof(info->timestamp.flags)); + offset += sizeof(info->timestamp.flags); + break; + case IEEE80211_RADIOTAP_RTS_RETRIES: + memcpy(rtap_data + offset, &info->rts_retries, sizeof(info->rts_retries)); + offset += sizeof(info->rts_retries); + break; + case IEEE80211_RADIOTAP_DATA_RETRIES: + memcpy(rtap_data + offset, &info->data_retries, sizeof(info->data_retries)); + offset += sizeof(info->data_retries); + break; + } + } + + presence_bit >>= 1; + } + + rtap_hdr.it_len += offset; + + memcpy(radiotap_header, &rtap_hdr, sizeof(struct ieee80211_radiotap_header)); + memcpy(radiotap_header + sizeof(struct ieee80211_radiotap_header), &rtap_data, offset); + + return rtap_hdr.it_len; +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_GEN_RADIOTAP_H +#define LIBWIFI_GEN_RADIOTAP_H + +#include "../../core/misc/radiotap.h" +#include + +/* + * Generate a customised radiotap header based on the input provided in info. + * + * @param info A libwifi_radiotap_info struct with desired radiotap data. + * @param radiotap_header Buffer to write the radiotap header into. + * @return Length of the generated radiotap header. + */ +size_t libwifi_create_radiotap(struct libwifi_radiotap_info *info, char *radiotap_header); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "data.h" + +#include +#include +#include + +int libwifi_parse_data(struct libwifi_data *data, struct libwifi_frame *frame) { + if (frame->frame_control.type != TYPE_DATA) { + return -EINVAL; + } + + if (frame->flags & LIBWIFI_FLAGS_IS_QOS) { + memcpy(data->receiver, frame->header.data_qos.addr1, 6); + memcpy(data->transmitter, frame->header.data_qos.addr2, 6); + } else { + memcpy(data->receiver, frame->header.data.addr1, 6); + memcpy(data->transmitter, frame->header.data.addr2, 6); + } + + data->body_len = frame->len - frame->header_len; + + data->body = malloc(data->body_len); + if (data->body == NULL) { + return -ENOMEM; + } + memcpy(frame->body, data->body, data->body_len); + + return 0; +} + +void libwifi_free_data(struct libwifi_data *data) { + free(data->body); +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_PARSE_DATA_H +#define LIBWIFI_PARSE_DATA_H + +#include "../../core/frame/data/data.h" +#include "../../core/frame/frame.h" + +int libwifi_parse_data(struct libwifi_data *data, struct libwifi_frame *frame); + +void libwifi_free_data(struct libwifi_data *data); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "eapol.h" +#include "../../core/frame/frame.h" +#include "../../core/misc/byteswap.h" +#include "../../core/misc/llc.h" +#include "../../core/misc/security.h" + +#include +#include +#include +#include +#include + +/** + * A libwifi_frame is deemed to be an EAPOL handshake if the following criteria is met: + * - The frame is of type TYPE_DATA, and + * - The frame contains a logical link control layer, and + * - There is enough data in the frame body to fill a libwifi_wpa_auth_data struct. + */ +int libwifi_check_wpa_handshake(struct libwifi_frame *frame) { + // WPA Handshakes are transmitted in EAPOL frames + if (frame->frame_control.type != TYPE_DATA) { + return -EINVAL; + } + + // Data frame must be at least the length of the header plus the encapsulating LLC + if (frame->len < (frame->header_len + sizeof(struct libwifi_logical_link_ctrl))) { + return -EINVAL; + } + + // Represent the LLC layer so that we can check the OUI and ensure it is correct + struct libwifi_logical_link_ctrl *llc = (struct libwifi_logical_link_ctrl *) (frame->body); + if (memcmp(llc->oui, XEROX_OUI, sizeof(llc->oui)) != 0) { + return -EINVAL; + } + + // Match the network byte-order of LLC and ensure we have a frame containing 802.1X information + if (ntohs(llc->type) != LLC_TYPE_AUTH) { + return -EINVAL; + } + + // Ensure we have enough information in the frame to fill a libwifi_wpa_auth_data struct + // This value is calculated by ensuring the frame is at least the length of the LLC layer, plus the length + // of the libwifi_wpa_auth_data struct, however, the length of an unsigned char pointer is subtracted due + // to the possibility of the frame having no WPA key data. + size_t required_data_length = + frame->header_len + (sizeof(struct libwifi_logical_link_ctrl) + + (sizeof(struct libwifi_wpa_auth_data) - sizeof(unsigned char *))); + if (frame->len < required_data_length) { + return -EINVAL; + } + + return 1; +} + +/* + * The specific EAPOL message in the supplied libwifi_frame is determined via the 802.1X key information + * field. + */ +int libwifi_check_wpa_message(struct libwifi_frame *frame) { + // Ensure we have enough information in the frame to fill a libwifi_wpa_auth_data struct + // This value is calculated by ensuring the frame is at least the length of the LLC layer, plus the length + // of the libwifi_wpa_auth_data struct, however, the length of an unsigned char pointer is subtracted due + // to the possibility of the frame having no WPA key data. + size_t required_data_length = + frame->header_len + (sizeof(struct libwifi_logical_link_ctrl) + + (sizeof(struct libwifi_wpa_auth_data) - sizeof(unsigned char *))); + if (frame->len < required_data_length) { + return HANDSHAKE_INVALID; + } + + struct libwifi_wpa_auth_data *auth_data = + (struct libwifi_wpa_auth_data *) (frame->body + sizeof(struct libwifi_logical_link_ctrl)); + switch (ntohs(auth_data->key_info.information)) { + case EAPOL_KEY_INFO_M1: + return HANDSHAKE_M1; + case EAPOL_KEY_INFO_M2: + return HANDSHAKE_M2; + case EAPOL_KEY_INFO_M3: + return HANDSHAKE_M3; + case EAPOL_KEY_INFO_M4: + return HANDSHAKE_M4; + default: + return HANDSHAKE_INVALID; + } +} + +/* + * Simple helper function to print a string depending on the EAPOL message + */ +const char *libwifi_get_wpa_message_string(struct libwifi_frame *frame) { + int message = libwifi_check_wpa_message(frame); + + switch (message) { + case HANDSHAKE_M1: + return "Message 1"; + case HANDSHAKE_M2: + return "Message 2"; + case HANDSHAKE_M3: + return "Message 3"; + case HANDSHAKE_M4: + return "Message 4"; + case HANDSHAKE_INVALID: + default: + return "Invalid"; + } +} + +/* + * The value returned here is the length of the data available _after_ the rest of the EAPOL data, + * and should be used for obtaining the EAPOL Key Data, if present. + */ +int libwifi_get_wpa_key_data_length(struct libwifi_frame *frame) { + if (libwifi_check_wpa_handshake(frame) < 0) { + return -EINVAL; + } + + struct libwifi_wpa_auth_data *auth_data = + (struct libwifi_wpa_auth_data *) (frame->body + sizeof(struct libwifi_logical_link_ctrl)); + + // Byte-swap the multi-byte length key_data_length for the host system + return ntohs(auth_data->key_info.key_data_length); +} + +/* + * Data in the supplied libwifi_frame is expected to be in network byte order. To avoid confusion, this + * data is byte-swapped to the host system's endianess. + * + * If the supplied key_data is not NULL, any key data at the end of the frame will be written into the + * supplied key_data buffer. You can obtain the length to malloc such a buffer with + * libwifi_get_wpa_key_data_length. + */ +int libwifi_get_wpa_data(struct libwifi_frame *frame, struct libwifi_wpa_auth_data *data) { + memset(data, 0, sizeof(struct libwifi_wpa_auth_data)); + + if (libwifi_check_wpa_handshake(frame) < 0) { + return -EINVAL; + } + + struct libwifi_wpa_auth_data *auth_data = + (struct libwifi_wpa_auth_data *) (frame->body + sizeof(struct libwifi_logical_link_ctrl)); + + // Multi-byte fields will be byte-swapped to the host byte order + data->version = auth_data->version; + data->type = auth_data->type; + data->length = ntohs(auth_data->length); + data->descriptor = auth_data->descriptor; + memcpy(&data->key_info, &auth_data->key_info, sizeof(struct libwifi_wpa_key_info)); + data->key_info.information = ntohs(auth_data->key_info.information); + data->key_info.key_length = ntohs(auth_data->key_info.key_length); + data->key_info.replay_counter = be64toh(auth_data->key_info.replay_counter); + data->key_info.key_data_length = ntohs(auth_data->key_info.key_data_length); + + if (data->key_info.key_data_length > 0) { + // Prevent huge allocations in corrupted or malicious frames + if (data->key_info.key_data_length > 1024) { + data->key_info.key_data_length = 1024; + } + + data->key_info.key_data = malloc(data->key_info.key_data_length); + if (data->key_info.key_data == NULL) { + return -ENOMEM; + } + size_t key_data_offset = sizeof(struct libwifi_logical_link_ctrl) + + sizeof(struct libwifi_wpa_auth_data) - sizeof(unsigned char *); + memcpy(data->key_info.key_data, frame->body + key_data_offset, data->key_info.key_data_length); + } + + return 0; +} + +void libwifi_free_wpa_data(struct libwifi_wpa_auth_data *data) { + if (data->key_info.key_data_length > 0) { + free(data->key_info.key_data); + } +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_PARSE_EAPOL_H +#define LIBWIFI_PARSE_EAPOL_H + +#include "../../core/frame/frame.h" +#include "../../core/misc/security.h" + +enum WPA_HANDSHAKE_PART { + HANDSHAKE_M1 = 1, + HANDSHAKE_M2 = 2, + HANDSHAKE_M3 = 4, + HANDSHAKE_M4 = 8, + HANDSHAKE_INVALID = 16 +}; + +/** + * Check if a libwifi_frame contains a WPA1/2 handshake message. + * + * @param libwifi_frame A libwifi_frame + * @return 1 if a handshake is detected, 0 if not. + */ +int libwifi_check_wpa_handshake(struct libwifi_frame *frame); + +/** + * Check what message of the WPA1/2 handshake is in the given frame. + * + * The returned value can be used with the WPA_HANDSHAKE_PART enum, + * such as: + * + * part = libwifi_check_wpa_message(frame); + * if (part & HANDSHAKE_M1) { + * // This is EAPOL Message 1 + * } + * + * @param libwifi_frame A libwifi_frame + * @return A bitmask of parts. + */ +int libwifi_check_wpa_message(struct libwifi_frame *frame); + +/** + * Get a string describing the WPA handshake message inside a supplied libwifi_frame. + * + * @param libwifi_frame A libwifi_frame + * @return A string describing the WPA handshake message found + */ +const char *libwifi_get_wpa_message_string(struct libwifi_frame *frame); + +/** + * Get the length of the key data, if any, present at the end of an EAPOL frame. + * + * @param libwifi_frame A libwifi_frame + * @return The length of the key data + */ +int libwifi_get_wpa_key_data_length(struct libwifi_frame *frame); + +/** + * Get the EAPOL/WPA information from a given libwifi_frame. + * + * As the values in the frame below and including the logical link control layer will be in + * network byte order, the values will be automatically byte swapped if necessary to match + * the host systems byte order. + * + * @param libwifi_frame A libwifi_frame + * @param data A pointer to a libwifi_wpa_auth_data struct + * @return 0 on success, -1 on failure + */ +int libwifi_get_wpa_data(struct libwifi_frame *frame, struct libwifi_wpa_auth_data *data); + +/** + * Free any memory allocated inside of a libwifi_wpa_auth data, such as a buffer + * for WPA key data allocated by the library. + * + * @param data A pointer to a libwifi_wpa_auth_data struct + */ +void libwifi_free_wpa_data(struct libwifi_wpa_auth_data *data); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "assoc_request.h" +#include "../../core/frame/tag_iterator.h" +#include "common.h" + +#include +#include +#include + +/** + * libwifi_parse_assoc_req will parse useful fields into a struct libwifi_sta. + * + * This function also checks to see if the transmitter address can be ANDed + * with 0x02, to determine a likelihood of randomized addresses. + * + * ┌─────────────────────────────────────────────┐ + * │ Header (Ordered or Unordered) │ ── Association Request Header + * ├─────────────────────────────────────────────┤ + * │ Fixed Parameters │ ─┐ + * ├─────────────────────────────────────────────┤ ├── Association Request Body + * │ Tagged Parameters │ ─┘ + * └─────────────────────────────────────────────┘ + */ +int libwifi_parse_assoc_req(struct libwifi_sta *sta, struct libwifi_frame *frame) { + memset(sta, 0, sizeof(struct libwifi_sta)); + + if (frame->frame_control.type != TYPE_MANAGEMENT || frame->frame_control.subtype != SUBTYPE_ASSOC_REQ) { + return -EINVAL; + } + + if (frame->frame_control.flags.ordered) { + memcpy(sta->transmitter, frame->header.mgmt_ordered.addr2, 6); + memcpy(sta->bssid, frame->header.mgmt_ordered.addr3, 6); + } else { + memcpy(sta->transmitter, frame->header.mgmt_unordered.addr2, 6); + memcpy(sta->bssid, frame->header.mgmt_unordered.addr3, 6); + } + + if (sta->transmitter[0] & 0x02) { + sta->randomized = 1; + } else { + sta->randomized = 0; + } + + // Fixed Parameters must be present + if (frame->len <= (frame->header_len + sizeof(struct libwifi_assoc_req_fixed_parameters))) { + return -EINVAL; + } + + sta->tags.length = (frame->len - frame->header_len); + const unsigned char *tagged_params = frame->body; + sta->tags.parameters = malloc(sta->tags.length); + memcpy(sta->tags.parameters, tagged_params, sta->tags.length); + + struct libwifi_tag_iterator it; + if (libwifi_tag_iterator_init(&it, sta->tags.parameters, sta->tags.length) != 0) { + return -EINVAL; + } + + if (libwifi_sta_tag_parser(sta, &it) != 0) { + return -EINVAL; + } + + return 0; +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_PARSE_ASSOCREQ_H +#define LIBWIFI_PARSE_ASSOCREQ_H + +#include "../../core/frame/frame.h" +#include "../../core/frame/management/assoc_request.h" +#include "../../core/frame/management/common.h" + +/** + * Parse a association request into a libwifi_sta. + * + * @param sta A libwifi_sta + * @param frame A libwifi_frame + * @return 0 if successful, a negative number if not + */ +int libwifi_parse_assoc_req(struct libwifi_sta *sta, struct libwifi_frame *frame); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../../core/frame/management/assoc_response.h" +#include "../../core/frame/frame.h" +#include "../../core/frame/tag.h" +#include "../../core/frame/tag_iterator.h" +#include "../../core/misc/types.h" +#include "../../parse/misc/security.h" +#include "assoc_response.h" +#include "common.h" + +#include +#include +#include + +/** + * libwifi_parse_assoc_resp will parse useful information out of a Probe Response + * into a struct libwifi_bss. As Probe Response frames are very similar to Beacon + * frames, they can be treated in much the same way. + * + * ┌─────────────────────────────────────────────┐ + * │ Header (Ordered or Unordered) │ ── Probe Response Header + * ├─────────────────────────────────────────────┤ + * │ Fixed Parameters │ ─┐ + * ├─────────────────────────────────────────────┤ ├── Probe Response Body + * │ Tagged Parameters │ ─┘ + * └─────────────────────────────────────────────┘ + */ +int libwifi_parse_assoc_resp(struct libwifi_bss *bss, struct libwifi_frame *frame) { + memset(bss, 0, sizeof(struct libwifi_bss)); + + if (frame->frame_control.type != TYPE_MANAGEMENT || frame->frame_control.subtype != SUBTYPE_ASSOC_RESP) { + return -EINVAL; + } + + if (frame->frame_control.flags.ordered) { + memcpy(bss->receiver, frame->header.mgmt_ordered.addr1, 6); + memcpy(bss->transmitter, frame->header.mgmt_ordered.addr2, 6); + memcpy(bss->bssid, frame->header.mgmt_ordered.addr3, 6); + } else { + memcpy(bss->receiver, frame->header.mgmt_unordered.addr1, 6); + memcpy(bss->transmitter, frame->header.mgmt_unordered.addr2, 6); + memcpy(bss->bssid, frame->header.mgmt_unordered.addr3, 6); + } + + // Fixed Parameters must be present + if (frame->len <= (frame->header_len + sizeof(struct libwifi_assoc_resp_fixed_parameters))) { + return -EINVAL; + } + + // At least one Tagged Parameter must be present + if (frame->len < (frame->header_len + sizeof(struct libwifi_assoc_resp_fixed_parameters) + 2)) { + return -EINVAL; + } + + struct libwifi_assoc_resp_fixed_parameters *fixed_params = + (struct libwifi_assoc_resp_fixed_parameters *) frame->body; + if (libwifi_check_capabilities(fixed_params->capabilities_information, CAPABILITIES_PRIVACY)) { + bss->encryption_info |= WEP; + } + + bss->tags.length = + (frame->len - (frame->header_len + sizeof(struct libwifi_assoc_resp_fixed_parameters))); + const unsigned char *tagged_params = frame->body + sizeof(struct libwifi_assoc_resp_fixed_parameters); + bss->tags.parameters = malloc(bss->tags.length); + memcpy(bss->tags.parameters, tagged_params, bss->tags.length); + + // Iterate through common BSS tagged parameters (WPA, RSN, etc) + struct libwifi_tag_iterator it; + memset(&it, 0, sizeof(struct libwifi_tag_iterator)); + if (libwifi_tag_iterator_init(&it, bss->tags.parameters, bss->tags.length) != 0) { + return -EINVAL; + } + if (libwifi_bss_tag_parser(bss, &it) != 0) { + return -EINVAL; + }; + + return 0; +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_PARSE_ASSOCRESP_H +#define LIBWIFI_PARSE_ASSOCRESP_H + +#include +#include + +#include "../../core/frame/frame.h" +#include "../../core/frame/management/common.h" +#include "../../core/misc/security.h" + +/** + * Parse an association response frame into a libwifi_bss. + * + * @param bss A libwifi_bss + * @param frame A libwifi_frame + * @return 0 if successful, a negative number if not. + */ +int libwifi_parse_assoc_resp(struct libwifi_bss *bss, struct libwifi_frame *frame); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../../core/frame/management/beacon.h" +#include "../../core/frame/frame.h" +#include "../../core/frame/tag.h" +#include "../../core/frame/tag_iterator.h" +#include "../../core/misc/types.h" +#include "../../parse/misc/security.h" +#include "beacon.h" +#include "common.h" + +#include +#include +#include +#include + +/** + * libwifi_parse_beacon will parse useful fields out of a supplied beacon frame + * in the format of a struct libwifi_frame. + * + * ┌─────────────────────────────────────────────┐ + * │ Header (Ordered or Unordered) │ ── Beacon Header + * ├─────────────────────────────────────────────┤ + * │ Fixed Parameters │ ─┐ + * ├─────────────────────────────────────────────┤ ├── Beacon Body + * │ Tagged Parameters │ ─┘ + * └─────────────────────────────────────────────┘ + */ +int libwifi_parse_beacon(struct libwifi_bss *bss, struct libwifi_frame *frame) { + memset(bss, 0, sizeof(struct libwifi_bss)); + + if (frame->frame_control.type != TYPE_MANAGEMENT || frame->frame_control.subtype != SUBTYPE_BEACON) { + return -EINVAL; + } + + if (frame->frame_control.flags.ordered) { + memcpy(bss->receiver, frame->header.mgmt_ordered.addr1, 6); + memcpy(bss->transmitter, frame->header.mgmt_ordered.addr2, 6); + memcpy(bss->bssid, frame->header.mgmt_ordered.addr3, 6); + } else { + memcpy(bss->receiver, frame->header.mgmt_unordered.addr1, 6); + memcpy(bss->transmitter, frame->header.mgmt_unordered.addr2, 6); + memcpy(bss->bssid, frame->header.mgmt_unordered.addr3, 6); + } + + // Fixed Parameters must be present + if (frame->len <= (frame->header_len + sizeof(struct libwifi_beacon_fixed_parameters))) { + return -EINVAL; + } + + // At least one Tagged Parameter must be present + if (frame->len < (frame->header_len + sizeof(struct libwifi_beacon_fixed_parameters) + 2)) { + return -EINVAL; + } + + struct libwifi_beacon_fixed_parameters *fixed_params = + (struct libwifi_beacon_fixed_parameters *) frame->body; + if (libwifi_check_capabilities(fixed_params->capabilities_information, CAPABILITIES_PRIVACY)) { + bss->encryption_info |= WEP; + } + + bss->tags.length = (frame->len - (frame->header_len + sizeof(struct libwifi_beacon_fixed_parameters))); + const unsigned char *tagged_params = frame->body + sizeof(struct libwifi_beacon_fixed_parameters); + bss->tags.parameters = malloc(bss->tags.length); + memcpy(bss->tags.parameters, tagged_params, bss->tags.length); + + // Iterate through common BSS tagged parameters (WPA, RSN, etc) + struct libwifi_tag_iterator it; + memset(&it, 0, sizeof(struct libwifi_tag_iterator)); + if (libwifi_tag_iterator_init(&it, bss->tags.parameters, bss->tags.length) != 0) { + return -EINVAL; + } + if (libwifi_bss_tag_parser(bss, &it) != 0) { + return -EINVAL; + }; + + return 0; +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_PARSE_BEACON_H +#define LIBWIFI_PARSE_BEACON_H + +#include +#include + +#include "../../core/frame/frame.h" +#include "../../core/frame/management/common.h" +#include "../../core/misc/security.h" + +/** + * Parse useful properties from a beacon frame into a libwifi_bss. + * + * @param bss A libwifi_bss + * @param frame A libwifi_frame + * @return 0 if successful, a negative number if not. + */ +int libwifi_parse_beacon(struct libwifi_bss *bss, struct libwifi_frame *frame); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "common.h" +#include "../../core/frame/tag.h" +#include "../misc/security.h" + +#include +#include +#include +#include + +/** + * Different implementations can have variations of hidden SSIDs. + * It is common to simply set the SSID to an empty string, but some + * devices may "blank" the real SSID without reducing the character count. + * + * Example: "My-SSID" -> "\x00\x00\x00\x00\x00\x00\x00" + */ +void libwifi_handle_ssid_tag(void *target, int target_type, const char *tag_data, int tag_len) { + int hidden = 0; + int null_ssid = 1; + + if (tag_len <= 0) { + hidden = 1; + } else if (tag_len > 32) { + tag_len = 32; + } + + for (int i = 0; i < tag_len; i++) { + if (memcmp(&tag_data[i], "\x00", 1) != 0) { + null_ssid = 0; + break; + } + } + + if (null_ssid) { + hidden = 1; + } + + if (target_type == LIBWIFI_BSS) { + struct libwifi_bss *bss = (struct libwifi_bss *) target; + memcpy(bss->ssid, tag_data, tag_len); + bss->hidden = hidden; + } else if (target_type == LIBWIFI_STA) { + struct libwifi_sta *sta = (struct libwifi_sta *) target; + memcpy(sta->ssid, tag_data, tag_len); + } +} + +/** + * Handle the RSN Tagged Parameter. + * + * At the minimum, the required RSN data is the version and the group cipher suites. + * RSN information is then enumerated within the libwifi_get_rsn_info() function. + */ +int libwifi_bss_handle_rsn_tag(struct libwifi_bss *bss, const unsigned char *rsn_data, int rsn_len) { + struct libwifi_rsn_info rsn_info = {0}; + + bss->encryption_info &= ~(unsigned int) WEP; + + int min_len = sizeof(rsn_info.rsn_version) + sizeof(struct libwifi_cipher_suite); + if (rsn_len < min_len) { + return -EINVAL; + } + + const unsigned char *rsn_end = rsn_data + rsn_len; + + if ((libwifi_get_rsn_info(&rsn_info, rsn_data, rsn_end) != 0)) { + return -EINVAL; + } + + libwifi_enumerate_rsn_suites(&rsn_info, bss); + + memcpy(&bss->rsn_info, &rsn_info, sizeof(struct libwifi_rsn_info)); + + return 0; +} + +/** + * The Microsoft vendor tag is used to advertise WPA and WPS information, as well as + * some other features such as WMM/WME. + * + * The difference between the tags is found via the "Vendor Specific OUI Type" field. + * A common representation of this is XX:XX:XX:YY, such as 00:50:F2:04, where + * 00:50:F2 is the Microsoft OUI and 04 is the type. + * + * It is important to skip the OUI and Type as described above before parsing the data of + * the tag. This is encapsulated with the libwifi_tag_vendor_header struct. + */ +int libwifi_bss_handle_msft_tag(struct libwifi_bss *bss, const unsigned char *msft_data, int msft_len) { + struct libwifi_wpa_info wpa_info = {0}; + struct libwifi_tag_vendor_header *vendor_header = (struct libwifi_tag_vendor_header *) msft_data; + + switch (vendor_header->type) { + case MICROSOFT_OUI_TYPE_WPA: + bss->encryption_info &= ~(unsigned int) WEP; + bss->encryption_info |= WPA; + + // Skip 4 bytes for the OUI (3) and Vendor Tag Type (1) + const unsigned char *wpa_data = msft_data + sizeof(struct libwifi_tag_vendor_header); + const unsigned char *wpa_end = msft_data + (msft_len + sizeof(struct libwifi_tag_vendor_header)); + + if ((libwifi_get_wpa_info(&wpa_info, wpa_data, wpa_end) != 0)) { + return -EINVAL; + } + + libwifi_enumerate_wpa_suites(&wpa_info, bss); + + memcpy(&bss->wpa_info, &wpa_info, sizeof(struct libwifi_wpa_info)); + break; + case MICROSOFT_OUI_TYPE_WMM: + // WMM/WME Supported + break; + case MICROSOFT_OUI_TYPE_WPS: + bss->wps = 1; + break; + } + + return 0; +} + +/** + * This function is a parser for common and useful tags found in frames usually originating + * from the BSS. These include the SSID and DS or HT fields, which can be used to determine + * the channel. + */ +int libwifi_bss_tag_parser(struct libwifi_bss *bss, struct libwifi_tag_iterator *it) { + struct libwifi_tag_vendor_header *vendor_header = NULL; + + do { + switch (it->tag_header->tag_num) { + case TAG_SSID: + libwifi_handle_ssid_tag((void *) bss, LIBWIFI_BSS, (const char *) it->tag_data, + it->tag_header->tag_len); + break; + case TAG_DS_PARAMETER: + case TAG_HT_OPERATION: + memcpy(&bss->channel, it->tag_data, 1); + break; + case TAG_RSN: + if ((libwifi_bss_handle_rsn_tag(bss, it->tag_data, it->tag_header->tag_len) != 0)) { + return -EINVAL; + }; + break; + case TAG_VENDOR_SPECIFIC: + vendor_header = (struct libwifi_tag_vendor_header *) it->tag_data; + + if (memcmp(vendor_header->oui, MICROSOFT_OUI, 3) == 0) { + if ((libwifi_bss_handle_msft_tag(bss, it->tag_data, it->tag_header->tag_len) != 0)) { + return -EINVAL; + } + } + break; + } + } while (libwifi_tag_iterator_next(it) != -1); + + return 0; +} + +/** + * This function is a parser for common and useful tags found in frames usually originating + * from the STA. These include the SSID and DS or HT fields, which can be used to determine + * the channel. + */ +int libwifi_sta_tag_parser(struct libwifi_sta *sta, struct libwifi_tag_iterator *it) { + do { + switch (it->tag_header->tag_num) { + case TAG_SSID: + libwifi_handle_ssid_tag(sta, LIBWIFI_STA, (const char *) it->tag_data, + it->tag_header->tag_len); + break; + case TAG_DS_PARAMETER: + memcpy(&sta->channel, it->tag_data, 1); + break; + } + } while (libwifi_tag_iterator_next(it) != -1); + + return 0; +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_PARSE_MGMT_COMMON_H +#define LIBWIFI_PARSE_MGMT_COMMON_H + +#include "../../core/frame/management/common.h" +#include "../../core/frame/tag_iterator.h" +#include "../../core/misc/security.h" + +/** + * A helper function to set the SSID of a libwifi_bss, as well as check + * if it is hidden or not. + * + * @param target A libwifi_bss or libwifi_sta + * @param target_type LIBWIFI_BSS or LIBWIFI_STA + * @param ssid The SSID to set + * @param ssid_len The length of the supplied SSID + */ +void libwifi_handle_ssid_tag(void *target, int target_type, const char *ssid, int ssid_len); + +/** + * A helper function to handle the parsing of the RSN IE. + * + * @param bss A libwifi_bss + * @param rsn_data The RSN tag data + * @param rsn_len The length of the RSN tag data + */ +int libwifi_bss_handle_rsn_tag(struct libwifi_bss *bss, const unsigned char *rsn_data, int rsn_len); + +/** + * A helper function to handle the parsing of the Microsoft Vendor IE. + * + * @param bss A libwifi_bss + * @param msft_data The Microsoft vendor tag data + * @param msft_len The length of the Microsoft tag data + */ +int libwifi_bss_handle_msft_tag(struct libwifi_bss *bss, const unsigned char *msft_data, int msft_len); + +/** + * A helper function to iterate through common tags found in a libwifi_bss. + * + * @param bss A libwifi_bss + * @param it A libwifi_tag_iterator + * @return 0 if successful, a negative number if not + */ +int libwifi_bss_tag_parser(struct libwifi_bss *bss, struct libwifi_tag_iterator *it); + +/** + * A helper function to iterate through common tags found in a libwifi_sta. + * + * @param sta A libwifi_sta + * @param it A libwifi_tag_iterator + * @return 0 if successful, a negative number if not + */ +int libwifi_sta_tag_parser(struct libwifi_sta *sta, struct libwifi_tag_iterator *it); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "deauthentication.h" +#include "common.h" + +#include +#include +#include + +/** + * TODO: potentally write a parsed_to_gen function that converts a parsed deauth back into + * something that can be passed directly into the interface? + */ + +/** + * Deauthentication frames can originate from the BSS or the STA, with no way to know + * who sent the frame by looking at just the frame alone. Because of this, they are + * parsed into a struct libwifi_parsed_deauth instead of a libwifi_bss or libwifi_sta. + * + * ┌─────────────────────────────────────────────┐ + * │ Header (Ordered or Unordered) │ ── Deauthentication Header + * ├─────────────────────────────────────────────┤ + * │ Fixed Parameters │ ─┐ + * ├─────────────────────────────────────────────┤ ├── Deauthentication Body + * │ Tagged Parameters │ ─┘ + * └─────────────────────────────────────────────┘ + */ +int libwifi_parse_deauth(struct libwifi_parsed_deauth *deauth, struct libwifi_frame *frame) { + memset(deauth, 0, sizeof(struct libwifi_parsed_deauth)); + + int tags_len = 0; + + if (frame->frame_control.type != TYPE_MANAGEMENT || frame->frame_control.subtype != SUBTYPE_DEAUTH) { + return -EINVAL; + } + + deauth->ordered = frame->frame_control.flags.ordered; + + if (deauth->ordered) { + memcpy(&deauth->frame_header.ordered, &frame->header.mgmt_ordered, + sizeof(struct libwifi_mgmt_ordered_frame_header)); + tags_len = (frame->len - sizeof(struct libwifi_mgmt_ordered_frame_header) - + sizeof(struct libwifi_deauth_fixed_parameters)); + } else { + memcpy(&deauth->frame_header.unordered, &frame->header.mgmt_unordered, + sizeof(struct libwifi_mgmt_unordered_frame_header)); + tags_len = (frame->len - sizeof(struct libwifi_mgmt_unordered_frame_header) - + sizeof(struct libwifi_deauth_fixed_parameters)); + } + + unsigned char *body = (unsigned char *) frame->body; + + memcpy(&deauth->fixed_parameters, body, sizeof(struct libwifi_deauth_fixed_parameters)); + body += sizeof(struct libwifi_deauth_fixed_parameters); + + deauth->tags.parameters = malloc(tags_len); + memcpy(&deauth->tags.parameters, body, tags_len); + memcpy(&deauth->tags.length, &tags_len, sizeof(tags_len)); + + return 0; +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_PARSE_DEAUTH_H +#define LIBWIFI_PARSE_DEAUTH_H + +#include "../../core/frame/frame.h" +#include "../../core/frame/management/common.h" +#include "../../core/frame/management/deauthentication.h" + +int libwifi_parse_deauth(struct libwifi_parsed_deauth *deauth, struct libwifi_frame *frame); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "disassociation.h" +#include "common.h" + +#include +#include + +/** + * TODO: potentally write a parsed_to_gen function that converts a parsed disassoc back into + * something that can be passed directly into the interface? + */ + +/** + * Disassociation frames can originate from the BSS or the STA, with no way to know + * who sent the frame by looking at just the frame alone. Because of this, they are + * parsed into a struct libwifi_parsed_deauth instead of a libwifi_bss or libwifi_sta. + * + * ┌─────────────────────────────────────────────┐ + * │ Header (Ordered or Unordered) │ ── Disassociation Header + * ├─────────────────────────────────────────────┤ + * │ Fixed Parameters │ ─┐ + * ├─────────────────────────────────────────────┤ ├── Disassociation Body + * │ Tagged Parameters │ ─┘ + * └─────────────────────────────────────────────┘ + */ +int libwifi_parse_disassoc(struct libwifi_parsed_disassoc *disassoc, struct libwifi_frame *frame) { + memset(disassoc, 0, sizeof(struct libwifi_parsed_disassoc)); + + int tags_len = 0; + + if (frame->frame_control.type != TYPE_MANAGEMENT || frame->frame_control.subtype != SUBTYPE_DISASSOC) { + return -EINVAL; + } + + disassoc->ordered = frame->frame_control.flags.ordered; + + if (disassoc->ordered) { + memcpy(&disassoc->frame_header.ordered, &frame->header.mgmt_ordered, + sizeof(struct libwifi_mgmt_ordered_frame_header)); + tags_len = (frame->len - sizeof(struct libwifi_mgmt_ordered_frame_header) - + sizeof(struct libwifi_disassoc_fixed_parameters)); + } else { + memcpy(&disassoc->frame_header.unordered, &frame->header.mgmt_unordered, + sizeof(struct libwifi_mgmt_unordered_frame_header)); + tags_len = (frame->len - sizeof(struct libwifi_mgmt_unordered_frame_header) - + sizeof(struct libwifi_disassoc_fixed_parameters)); + } + + unsigned char *body = (unsigned char *) frame->body; + + memcpy(&disassoc->fixed_parameters, body, sizeof(struct libwifi_disassoc_fixed_parameters)); + body += sizeof(struct libwifi_disassoc_fixed_parameters); + + memcpy(&disassoc->tags, body, tags_len); + body += tags_len; + + return 0; +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_PARSE_DISASSOC_H +#define LIBWIFI_PARSE_DISASSOC_H + +#include "../../core/frame/frame.h" +#include "../../core/frame/management/common.h" +#include "../../core/frame/management/disassociation.h" + +int libwifi_parse_disassoc(struct libwifi_parsed_disassoc *disassoc, struct libwifi_frame *frame); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "probe_request.h" +#include "../../core/frame/tag_iterator.h" +#include "common.h" + +#include +#include +#include + +/** + * libwifi_parse_probe_req will parse useful fields into a struct libwifi_sta. + * + * This function also checks to see if the transmitter address can be ANDed + * with 0x02, to determine a likelihood of randomized addresses. + * + * ┌─────────────────────────────────────────────┐ + * │ Header (Ordered or Unordered) │ ── Probe Request Header + * ├─────────────────────────────────────────────┤ + * │ Tagged Parameters │ ── Probe Request Body + * └─────────────────────────────────────────────┘ + */ +int libwifi_parse_probe_req(struct libwifi_sta *sta, struct libwifi_frame *frame) { + memset(sta, 0, sizeof(struct libwifi_sta)); + + if (frame->frame_control.type != TYPE_MANAGEMENT || frame->frame_control.subtype != SUBTYPE_PROBE_REQ) { + return -EINVAL; + } + + if (frame->frame_control.flags.ordered) { + memcpy(sta->transmitter, frame->header.mgmt_ordered.addr2, 6); + memcpy(sta->bssid, frame->header.mgmt_ordered.addr3, 6); + } else { + memcpy(sta->transmitter, frame->header.mgmt_unordered.addr2, 6); + memcpy(sta->bssid, frame->header.mgmt_unordered.addr3, 6); + } + + if (sta->transmitter[0] & 0x02) { + sta->randomized = 1; + } else { + sta->randomized = 0; + } + + sta->tags.length = (frame->len - frame->header_len); + const unsigned char *tagged_params = frame->body; + sta->tags.parameters = malloc(sta->tags.length); + memcpy(sta->tags.parameters, tagged_params, sta->tags.length); + + struct libwifi_tag_iterator it; + if (libwifi_tag_iterator_init(&it, sta->tags.parameters, sta->tags.length) != 0) { + return -EINVAL; + } + + if (libwifi_sta_tag_parser(sta, &it) != 0) { + return -EINVAL; + } + + return 0; +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_PARSE_PROBEREQ_H +#define LIBWIFI_PARSE_PROBEREQ_H + +#include "../../core/frame/frame.h" +#include "../../core/frame/management/common.h" +#include "../../core/frame/management/probe_request.h" + +/** + * Parse a probe request into a libwifi_sta. + * + * @param sta A libwifi_sta + * @param frame A libwifi_frame + * @return 0 if successful, a negative number if not + */ +int libwifi_parse_probe_req(struct libwifi_sta *sta, struct libwifi_frame *frame); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../../core/frame/management/probe_response.h" +#include "../../core/frame/frame.h" +#include "../../core/frame/tag.h" +#include "../../core/frame/tag_iterator.h" +#include "../../core/misc/types.h" +#include "../../parse/misc/security.h" +#include "common.h" +#include "probe_response.h" + +#include +#include +#include + +/** + * libwifi_parse_probe_resp will parse useful information out of a Probe Response + * into a struct libwifi_bss. As Probe Response frames are very similar to Beacon + * frames, they can be treated in much the same way. + * + * ┌─────────────────────────────────────────────┐ + * │ Header (Ordered or Unordered) │ ── Probe Response Header + * ├─────────────────────────────────────────────┤ + * │ Fixed Parameters │ ─┐ + * ├─────────────────────────────────────────────┤ ├── Probe Response Body + * │ Tagged Parameters │ ─┘ + * └─────────────────────────────────────────────┘ + */ +int libwifi_parse_probe_resp(struct libwifi_bss *bss, struct libwifi_frame *frame) { + memset(bss, 0, sizeof(struct libwifi_bss)); + + if (frame->frame_control.type != TYPE_MANAGEMENT || frame->frame_control.subtype != SUBTYPE_PROBE_RESP) { + return -EINVAL; + } + + if (frame->frame_control.flags.ordered) { + memcpy(bss->bssid, frame->header.mgmt_ordered.addr3, 6); + } else { + memcpy(bss->bssid, frame->header.mgmt_unordered.addr3, 6); + } + + // Fixed Parameters must be present + if (frame->len <= (frame->header_len + sizeof(struct libwifi_probe_resp_fixed_parameters))) { + return -EINVAL; + } + + // At least one Tagged Parameter must be present + if (frame->len < (frame->header_len + sizeof(struct libwifi_probe_resp_fixed_parameters) + 2)) { + return -EINVAL; + } + + struct libwifi_probe_resp_fixed_parameters *fixed_params = + (struct libwifi_probe_resp_fixed_parameters *) frame->body; + if (libwifi_check_capabilities(fixed_params->capabilities_information, CAPABILITIES_PRIVACY)) { + bss->encryption_info |= WEP; + } + + bss->tags.length = + (frame->len - (frame->header_len + sizeof(struct libwifi_probe_resp_fixed_parameters))); + const unsigned char *tagged_params = frame->body + sizeof(struct libwifi_probe_resp_fixed_parameters); + bss->tags.parameters = malloc(bss->tags.length); + memcpy(bss->tags.parameters, tagged_params, bss->tags.length); + + // Iterate through common BSS tagged parameters (WPA, RSN, etc) + struct libwifi_tag_iterator it; + memset(&it, 0, sizeof(struct libwifi_tag_iterator)); + if (libwifi_tag_iterator_init(&it, bss->tags.parameters, bss->tags.length) != 0) { + return -EINVAL; + } + if (libwifi_bss_tag_parser(bss, &it) != 0) { + return -EINVAL; + }; + + return 0; +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_PARSE_PROBERESP_H +#define LIBWIFI_PARSE_PROBERESP_H + +#include +#include + +#include "../../core/frame/frame.h" +#include "../../core/frame/management/common.h" +#include "../../core/misc/security.h" + +/** + * Parse a probe response frame into a libwifi_bss. + * + * @param bss A libwifi_bss + * @param frame A libwifi_frame + * @return 0 if successful, a negative number if not. + */ +int libwifi_parse_probe_resp(struct libwifi_bss *bss, struct libwifi_frame *frame); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "reassoc_request.h" +#include "../../core/frame/tag_iterator.h" +#include "common.h" + +#include +#include +#include + +/** + * libwifi_parse_reassoc_req will parse useful fields into a struct libwifi_sta. + * + * This function also checks to see if the transmitter address can be ANDed + * with 0x02, to determine a likelihood of randomized addresses. + * + * ┌─────────────────────────────────────────────┐ + * │ Header (Ordered or Unordered) │ ── Ressociation Request Header + * ├─────────────────────────────────────────────┤ + * │ Fixed Parameters │ ─┐ + * ├─────────────────────────────────────────────┤ |── Ressociation Request Body + * │ Tagged Parameters │ ─┘ + * └─────────────────────────────────────────────┘ + */ +int libwifi_parse_reassoc_req(struct libwifi_sta *sta, struct libwifi_frame *frame) { + memset(sta, 0, sizeof(struct libwifi_sta)); + + if (frame->frame_control.type != TYPE_MANAGEMENT || frame->frame_control.subtype != SUBTYPE_REASSOC_REQ) { + return -EINVAL; + } + + if (frame->frame_control.flags.ordered) { + memcpy(sta->transmitter, frame->header.mgmt_ordered.addr2, 6); + memcpy(sta->bssid, frame->header.mgmt_ordered.addr3, 6); + } else { + memcpy(sta->transmitter, frame->header.mgmt_unordered.addr2, 6); + memcpy(sta->bssid, frame->header.mgmt_unordered.addr3, 6); + } + + if (sta->transmitter[0] & 0x02) { + sta->randomized = 1; + } else { + sta->randomized = 0; + } + + // Fixed Parameters must be present + if (frame->len <= (frame->header_len + sizeof(struct libwifi_reassoc_req_fixed_parameters))) { + return -EINVAL; + } + + sta->tags.length = (frame->len - frame->header_len); + const unsigned char *tagged_params = frame->body; + sta->tags.parameters = malloc(sta->tags.length); + memcpy(sta->tags.parameters, tagged_params, sta->tags.length); + + struct libwifi_tag_iterator it; + if (libwifi_tag_iterator_init(&it, sta->tags.parameters, sta->tags.length) != 0) { + return -EINVAL; + } + + if (libwifi_sta_tag_parser(sta, &it) != 0) { + return -EINVAL; + } + + return 0; +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_PARSE_REASSOCREQ_H +#define LIBWIFI_PARSE_REASSOCREQ_H + +#include "../../core/frame/frame.h" +#include "../../core/frame/management/common.h" +#include "../../core/frame/management/reassoc_request.h" + +/** + * Parse a reassociation request into a libwifi_sta. + * + * @param sta A libwifi_sta + * @param frame A libwifi_frame + * @return 0 if successful, a negative number if not + */ +int libwifi_parse_reassoc_req(struct libwifi_sta *sta, struct libwifi_frame *frame); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../../core/frame/management/reassoc_response.h" +#include "../../core/frame/frame.h" +#include "../../core/frame/tag.h" +#include "../../core/frame/tag_iterator.h" +#include "../../core/misc/types.h" +#include "../../parse/misc/security.h" +#include "common.h" +#include "reassoc_response.h" + +#include +#include +#include + +/** + * libwifi_parse_reassoc_resp will parse useful information out of a Reassocation Response + * into a struct libwifi_bss. + * + * ┌─────────────────────────────────────────────┐ + * │ Header (Ordered or Unordered) │ ── Reassocation Response Header + * ├─────────────────────────────────────────────┤ + * │ Fixed Parameters │ ─┐ + * ├─────────────────────────────────────────────┤ ├── Reassociation Response Body + * │ Tagged Parameters │ ─┘ + * └─────────────────────────────────────────────┘ + */ +int libwifi_parse_reassoc_resp(struct libwifi_bss *bss, struct libwifi_frame *frame) { + memset(bss, 0, sizeof(struct libwifi_bss)); + + if (frame->frame_control.type != TYPE_MANAGEMENT || + frame->frame_control.subtype != SUBTYPE_REASSOC_RESP) { + return -EINVAL; + } + + if (frame->frame_control.flags.ordered) { + memcpy(bss->receiver, frame->header.mgmt_ordered.addr1, 6); + memcpy(bss->transmitter, frame->header.mgmt_ordered.addr2, 6); + memcpy(bss->bssid, frame->header.mgmt_ordered.addr3, 6); + } else { + memcpy(bss->receiver, frame->header.mgmt_unordered.addr1, 6); + memcpy(bss->transmitter, frame->header.mgmt_unordered.addr2, 6); + memcpy(bss->bssid, frame->header.mgmt_unordered.addr3, 6); + } + + // Fixed Parameters must be present + if (frame->len <= (frame->header_len + sizeof(struct libwifi_reassoc_resp_fixed_parameters))) { + return -EINVAL; + } + + // At least one Tagged Parameter must be present + if (frame->len < (frame->header_len + sizeof(struct libwifi_reassoc_resp_fixed_parameters) + 2)) { + return -EINVAL; + } + + struct libwifi_reassoc_resp_fixed_parameters *fixed_params = + (struct libwifi_reassoc_resp_fixed_parameters *) frame->body; + if (libwifi_check_capabilities(fixed_params->capabilities_information, CAPABILITIES_PRIVACY)) { + bss->encryption_info |= WEP; + } + + bss->tags.length = + (frame->len - (frame->header_len + sizeof(struct libwifi_reassoc_resp_fixed_parameters))); + const unsigned char *tagged_params = frame->body + sizeof(struct libwifi_reassoc_resp_fixed_parameters); + bss->tags.parameters = malloc(bss->tags.length); + memcpy(bss->tags.parameters, tagged_params, bss->tags.length); + + // Iterate through common BSS tagged parameters (WPA, RSN, etc) + struct libwifi_tag_iterator it; + memset(&it, 0, sizeof(struct libwifi_tag_iterator)); + if (libwifi_tag_iterator_init(&it, bss->tags.parameters, bss->tags.length) != 0) { + return -EINVAL; + } + if (libwifi_bss_tag_parser(bss, &it) != 0) { + return -EINVAL; + }; + + return 0; +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_PARSE_REASSOCRESP_H +#define LIBWIFI_PARSE_REASSOCRESP_H + +#include +#include + +#include "../../core/frame/frame.h" +#include "../../core/frame/management/common.h" +#include "../../core/misc/security.h" + +/** + * Parse a reassociation response frame into a libwifi_bss. + * + * @param bss A libwifi_bss + * @param frame A libwifi_frame + * @return 0 if successful, a negative number if not. + */ +int libwifi_parse_reassoc_resp(struct libwifi_bss *bss, struct libwifi_frame *frame); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "radiotap.h" +#include "../../core/radiotap/radiotap_iter.h" + +#include +#include + +/** + * The libwifi radiotap parser uses the usual ieee80211_radiotap_iterator to parse incoming + * radiotap headers into a consumable libwifi_radiotap_info struct. + */ +void libwifi_parse_radiotap_info(struct libwifi_radiotap_info *info, const unsigned char *frame) { + memset(info, 0, sizeof(struct libwifi_radiotap_info)); + + struct ieee80211_radiotap_header *rh = (struct ieee80211_radiotap_header *) frame; + struct ieee80211_radiotap_iterator it = {0}; + int ret = ieee80211_radiotap_iterator_init(&it, (void *) frame, rh->it_len, NULL); + + int skipped_antenna = 0; + info->length = rh->it_len; + + while (!ret) { + switch (it.this_arg_index) { + case IEEE80211_RADIOTAP_CHANNEL: + info->channel.freq = le16toh(*(uint16_t *) it.this_arg); + info->channel.flags = le16toh(*(uint16_t *) (it.this_arg + 2)); + break; + case IEEE80211_RADIOTAP_RATE: + info->rate_raw = *it.this_arg; + info->rate = (*it.this_arg / 2.0); + break; + case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: + // Radiotap Headers will include the ANTSIGNAL without an explicit Antenna definition. + if (!skipped_antenna) { + info->signal = *it.this_arg; + skipped_antenna = 1; + break; + } + + if (info->antenna_count < LIBWIFI_MAX_RADIOTAP_ANTENNAS) { + struct libwifi_radiotap_antenna antenna = {.antenna_number = info->antenna_count, + .signal = *it.this_arg}; + info->antennas[info->antenna_count] = antenna; + info->antenna_count += 1; + } + break; + case IEEE80211_RADIOTAP_ANTENNA: + info->antennas[info->antenna_count - 1].antenna_number = *it.this_arg; + break; + case IEEE80211_RADIOTAP_DBM_ANTNOISE: + break; + case IEEE80211_RADIOTAP_FLAGS: + info->flags = *it.this_arg; + break; + case IEEE80211_RADIOTAP_EXT: + info->extended_flags = *it.this_arg; + break; + case IEEE80211_RADIOTAP_RX_FLAGS: + info->rx_flags = *it.this_arg; + break; + case IEEE80211_RADIOTAP_TX_FLAGS: + info->tx_flags = *it.this_arg; + break; + case IEEE80211_RADIOTAP_MCS: + info->mcs.known = *(uint8_t *) it.this_arg; + info->mcs.flags = *(uint8_t *) (it.this_arg + 2); + info->mcs.mcs = *(uint8_t *) (it.this_arg + 3); + break; + case IEEE80211_RADIOTAP_DBM_TX_POWER: + info->tx_power = *it.this_arg; + break; + case IEEE80211_RADIOTAP_TIMESTAMP: + info->timestamp.timestamp = le64toh(*(uint64_t *) it.this_arg); + info->timestamp.accuracy = le16toh(*(uint16_t *) (it.this_arg + 2)); + info->timestamp.unit = *(uint8_t *) (it.this_arg + 3); + info->timestamp.flags = *(uint8_t *) (it.this_arg + 4); + break; + case IEEE80211_RADIOTAP_RTS_RETRIES: + info->rts_retries = *it.this_arg; + break; + case IEEE80211_RADIOTAP_DATA_RETRIES: + info->data_retries = *it.this_arg; + break; + } + + ret = ieee80211_radiotap_iterator_next(&it); + } +} + +/** + * A simpler function than the main libwifi_parse_radiotap_info function, designed to extract + * only the signal strength field. + */ +int8_t libwifi_parse_radiotap_rssi(const unsigned char *frame) { + struct ieee80211_radiotap_header *rh = (struct ieee80211_radiotap_header *) frame; + + int8_t rssi = 0; + + struct ieee80211_radiotap_iterator it; + int ret = ieee80211_radiotap_iterator_init(&it, (void *) frame, rh->it_len, NULL); + + while (!ret) { + if (it.this_arg_index == IEEE80211_RADIOTAP_DBM_ANTSIGNAL) { + rssi = *it.this_arg; + break; + } + + ret = ieee80211_radiotap_iterator_next(&it); + } + + return rssi; +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_PARSE_RADIOTAP_H +#define LIBWIFI_PARSE_RADIOTAP_H + +#include "../../core/misc/radiotap.h" +#include + +/** + * Parse the radiotap information out of a raw frame into a + * libwifi_radiotap_info. + * + * @param info A libwifi_radiotap_info + * @param frame A raw 802.11 frame + */ +void libwifi_parse_radiotap_info(struct libwifi_radiotap_info *info, const unsigned char *frame); + +/** + * Retrieve the signal strength from a raw frame via radiotap header. + * + * @param frame A raw 802.11 frame + * @return signal strength in dBm + */ +int8_t libwifi_parse_radiotap_rssi(const unsigned char *frame); + +#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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "security.h" +#include "../../core/misc/byteswap.h" + +#include +#include +#include +#include + +/** + * RSN Information is supplied via the raw tag data. The supplied data is then "walked" + * through as a pointer to extract the details of the tag and write them into + * a struct libwifi_rsn_info. + * + * libwifi supports a maximum of 3 Pairwise Cipher Suites and 3 Auth Key Management Suites. + * The Version, Group Cipher Suite and Capabilities fields are all required. + */ +int libwifi_get_rsn_info(struct libwifi_rsn_info *info, const unsigned char *tag_data, + const unsigned char *tag_end) { + memset(info, 0, sizeof(struct libwifi_rsn_info)); + + // Create a pointer we can manipulate from the tag data + unsigned char *data = (unsigned char *) tag_data; + + // Handle the RSN Version + memcpy(&info->rsn_version, data, sizeof(info->rsn_version)); + data += sizeof(info->rsn_version); + + // Handle the RSN Group Cipher Suites + memcpy(&info->group_cipher_suite, data, sizeof(struct libwifi_cipher_suite)); + data += sizeof(struct libwifi_cipher_suite); + + // Bounds check and handle the RSN Pairwise Ciphers + if (data > tag_end) { + return -EINVAL; + } + if ((data + sizeof(uint16_t)) > tag_end) { + return -EINVAL; + } + uint16_t suite_count = *data; + if (suite_count > LIBWIFI_MAX_CIPHER_SUITES) { + suite_count = LIBWIFI_MAX_CIPHER_SUITES; + } + data += sizeof(suite_count); + if ((((suite_count * sizeof(struct libwifi_cipher_suite)) + data)) > tag_end) { + return -EINVAL; + } + info->num_pairwise_cipher_suites = suite_count; + + // Iterate through the found Pairwise Ciphers, adding them each time + struct wifi_cipher_suite *cur_cipher_suite = NULL; + for (int i = 0; i < suite_count; ++i) { + if (data > tag_end) { + return -EINVAL; + } + cur_cipher_suite = (struct wifi_cipher_suite *) data; + memcpy(&info->pairwise_cipher_suites[i], cur_cipher_suite, sizeof(struct libwifi_cipher_suite)); + info->pairwise_cipher_suites[i].suite_type = info->pairwise_cipher_suites[i].suite_type; + data += sizeof(struct libwifi_cipher_suite); + } + + // Bounds check and handle the RSN Authentication Key Management Suites + if ((data + sizeof(suite_count)) > tag_end) { + return -EINVAL; + } + suite_count = *data; + if (suite_count > LIBWIFI_MAX_CIPHER_SUITES) { + suite_count = LIBWIFI_MAX_CIPHER_SUITES; + } + data += sizeof(suite_count); + if ((((suite_count * sizeof(struct libwifi_cipher_suite)) + data)) > tag_end) { + return -EINVAL; + } + info->num_auth_key_mgmt_suites = suite_count; + + // Iterate through the found Auth Key Management Suites, adding them each time + for (int i = 0; i < suite_count; ++i) { + if (data > tag_end) { + return -EINVAL; + } + cur_cipher_suite = (struct wifi_cipher_suite *) data; + memcpy(&info->auth_key_mgmt_suites[i], cur_cipher_suite, sizeof(struct libwifi_cipher_suite)); + info->auth_key_mgmt_suites[i].suite_type = info->auth_key_mgmt_suites[i].suite_type; + data += sizeof(struct libwifi_cipher_suite); + } + + // Bounds check and handle the RSN Capabilities field + if (data > tag_end) { + return -EINVAL; + } + memcpy(&info->rsn_capabilities, data, sizeof(info->rsn_capabilities)); + + return 0; +} + +/** + * This function will enumerate over a supplied struct libwifi_rsn_info and write + * the following into a supplied struct libwifi_bss: + * + * - Group Cipher Suite + * - Up to 3 Pairwise Cipher Suites + * - Up to 3 Auth Key Management Suites + * - The WPA Type (WPA2 or WPA3) + * + * The bss->encryption_info field is a 64-bit wide bitmask. The larger length is + * required to accomodate the different types of cipher suites without having + * any overlap between group cipher and pairwise cipher. + */ +void libwifi_enumerate_rsn_suites(struct libwifi_rsn_info *rsn_info, struct libwifi_bss *bss) { + switch (rsn_info->group_cipher_suite.suite_type) { + case CIPHER_SUITE_WEP40: + bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_WEP40; + break; + case CIPHER_SUITE_TKIP: + bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_TKIP; + break; + case CIPHER_SUITE_RESERVED: + bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_RESERVED; + break; + case CIPHER_SUITE_CCMP128: + bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_CCMP128; + break; + case CIPHER_SUITE_WEP104: + bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_WEP104; + break; + case CIPHER_SUITE_BIP_CMAC128: + bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_BIP_CMAC128; + break; + case CIPHER_SUITE_NOTALLOWED: + bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_NOTALLOWED; + break; + case CIPHER_SUITE_GCMP128: + bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_GCMP128; + break; + case CIPHER_SUITE_GCMP256: + bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_GCMP256; + break; + case CIPHER_SUITE_CCMP256: + bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_CCMP256; + break; + case CIPHER_SUITE_BIP_GMAC128: + bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_BIP_GMAC128; + break; + case CIPHER_SUITE_BIP_GMAC256: + bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_BIP_GMAC256; + break; + case CIPHER_SUITE_BIP_CMAC256: + bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_BIP_CMAC256; + break; + default: + break; + } + + for (int i = 0; i < rsn_info->num_pairwise_cipher_suites; ++i) { + if ((memcmp(rsn_info->pairwise_cipher_suites[i].oui, CIPHER_SUITE_OUI, 3) == 0)) { + switch (rsn_info->pairwise_cipher_suites[i].suite_type) { + case CIPHER_SUITE_GROUP: + bss->encryption_info |= LIBWIFI_PAIRWISE_SUITE_GROUP; + break; + case CIPHER_SUITE_TKIP: + bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_TKIP; + break; + case CIPHER_SUITE_RESERVED: + bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_RESERVED; + break; + case CIPHER_SUITE_CCMP128: + bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_CCMP128; + break; + case CIPHER_SUITE_BIP_CMAC128: + bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_CMAC128; + break; + case CIPHER_SUITE_NOTALLOWED: + bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_NOTALLOWED; + break; + case CIPHER_SUITE_GCMP128: + bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_GCMP128; + break; + case CIPHER_SUITE_GCMP256: + bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_GCMP256; + break; + case CIPHER_SUITE_CCMP256: + bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_CCMP256; + break; + case CIPHER_SUITE_BIP_GMAC128: + bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_GMAC128; + break; + case CIPHER_SUITE_BIP_GMAC256: + bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_GMAC256; + break; + case CIPHER_SUITE_BIP_CMAC256: + bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_CMAC256; + break; + default: + break; + } + } + } + + for (int i = 0; i < rsn_info->num_auth_key_mgmt_suites; ++i) { + if (memcmp(rsn_info->auth_key_mgmt_suites[i].oui, CIPHER_SUITE_OUI, 3) == 0) { + switch (rsn_info->auth_key_mgmt_suites[i].suite_type) { + case AKM_SUITE_RESERVED: + bss->encryption_info |= WPA2; + bss->encryption_info |= LIBWIFI_AKM_SUITE_RESERVED; + break; + case AKM_SUITE_1X: + bss->encryption_info |= WPA2; + bss->encryption_info |= LIBWIFI_AKM_SUITE_1X; + break; + case AKM_SUITE_PSK: + bss->encryption_info |= WPA2; + bss->encryption_info |= LIBWIFI_AKM_SUITE_PSK; + break; + case AKM_SUITE_1X_FT: + bss->encryption_info |= WPA2; + bss->encryption_info |= LIBWIFI_AKM_SUITE_1X_FT; + break; + case AKM_SUITE_PSK_FT: + bss->encryption_info |= WPA2; + bss->encryption_info |= LIBWIFI_AKM_SUITE_PSK_FT; + break; + case AKM_SUITE_1X_SHA256: + bss->encryption_info |= WPA2; + bss->encryption_info |= LIBWIFI_AKM_SUITE_1X_SHA256; + break; + case AKM_SUITE_PSK_SHA256: + bss->encryption_info |= WPA2; + bss->encryption_info |= LIBWIFI_AKM_SUITE_PSK_SHA256; + break; + case AKM_SUITE_TDLS: + bss->encryption_info |= WPA2; + bss->encryption_info |= LIBWIFI_AKM_SUITE_TDLS; + break; + case AKM_SUITE_SAE: + bss->encryption_info |= WPA3; + bss->encryption_info |= LIBWIFI_AKM_SUITE_SAE; + break; + case AKM_SUITE_SAE_FT: + bss->encryption_info |= WPA3; + bss->encryption_info |= LIBWIFI_AKM_SUITE_SAE_FT; + break; + case AKM_SUITE_AP_PEER: + bss->encryption_info |= WPA3; + bss->encryption_info |= LIBWIFI_AKM_SUITE_AP_PEER; + break; + case AKM_SUITE_1X_SUITEB_SHA256: + bss->encryption_info |= WPA3; + bss->encryption_info |= LIBWIFI_AKM_SUITE_1X_SUITEB_SHA256; + break; + case AKM_SUITE_1X_SUITEB_SHA384: + bss->encryption_info |= WPA3; + bss->encryption_info |= LIBWIFI_AKM_SUITE_1X_SUITEB_SHA384; + break; + case AKM_SUITE_1X_FT_SHA384: + bss->encryption_info |= WPA3; + bss->encryption_info |= LIBWIFI_AKM_SUITE_1X_FT_SHA384; + break; + case AKM_SUITE_FILS_SHA256: + bss->encryption_info |= WPA2; + bss->encryption_info |= LIBWIFI_AKM_SUITE_FILS_SHA256; + break; + case AKM_SUITE_FILS_SHA384: + bss->encryption_info |= WPA3; + bss->encryption_info |= LIBWIFI_AKM_SUITE_FILS_SHA384; + break; + case AKM_SUITE_FILS_SHA256_FT: + bss->encryption_info |= WPA2; + bss->encryption_info |= LIBWIFI_AKM_SUITE_FILS_SHA256_FT; + break; + case AKM_SUITE_FILS_SHA384_FT: + bss->encryption_info |= WPA3; + bss->encryption_info |= LIBWIFI_AKM_SUITE_FILS_SHA384_FT; + break; + case AKM_SUITE_OWE: + bss->encryption_info |= WPA3; + bss->encryption_info |= LIBWIFI_AKM_SUITE_OWE; + break; + case AKM_PSK_SHA384_FT: + bss->encryption_info |= WPA3; + bss->encryption_info |= LIBWIFI_AKM_PSK_SHA384_FT; + break; + case AKM_PSK_SHA384: + bss->encryption_info |= WPA3; + bss->encryption_info |= LIBWIFI_AKM_PSK_SHA384; + break; + default: + break; + } + } + } +} + +/** + * Similar to libwifi_get_rsn_info, WPA Information is supplied via the raw tag data. + * The supplied data is then "walked" through as a pointer to extract the details of + * the tag and write them into a struct libwifi_wpa_info. + * + * libwifi supports a maximum of 3 Unicast Cipher Suites and 3 Auth Key Management Suites. + * The Version and Multicast Cipher Suite fields are required. + */ +int libwifi_get_wpa_info(struct libwifi_wpa_info *info, const unsigned char *tag_data, + const unsigned char *tag_end) { + memset(info, 0, sizeof(struct libwifi_wpa_info)); + + // Create a pointer we can manipulate from the tag data + unsigned char *data = ((unsigned char *) tag_data); + + // Handle the WPA Version + memcpy(&info->wpa_version, data, sizeof(info->wpa_version)); + data += sizeof(info->wpa_version); + + // Handle the WPA Multicast Cipher Suite + memcpy(&info->multicast_cipher_suite, data, sizeof(struct libwifi_cipher_suite)); + data += sizeof(struct libwifi_cipher_suite); + + // Bounds check and handle the WPA Unicast Cipher Suites + if (data > tag_end) { + return -EINVAL; + } + if ((data + sizeof(uint16_t)) > tag_end) { + return -EINVAL; + } + uint16_t suite_count = *data; + if (suite_count > LIBWIFI_MAX_CIPHER_SUITES) { + suite_count = LIBWIFI_MAX_CIPHER_SUITES; + } + data += sizeof(suite_count); + if ((((suite_count * sizeof(struct libwifi_cipher_suite)) + data)) > tag_end) { + return -EINVAL; + } + info->num_unicast_cipher_suites = suite_count; + + // Iterate through the found Unicast Ciphers, adding them each time + struct wifi_cipher_suite *cur_cipher_suite = NULL; + for (int i = 0; i < suite_count; ++i) { + if (data > tag_end) { + return -EINVAL; + } + cur_cipher_suite = (struct wifi_cipher_suite *) data; + memcpy(&info->unicast_cipher_suites[i], cur_cipher_suite, sizeof(struct libwifi_cipher_suite)); + info->unicast_cipher_suites[i].suite_type = info->unicast_cipher_suites[i].suite_type; + data += sizeof(struct libwifi_cipher_suite); + } + + // Bounds check and handle the WPA Authentication Key Management Suites + if ((data + sizeof(suite_count)) > tag_end) { + return -EINVAL; + } + suite_count = *data; + if (suite_count > LIBWIFI_MAX_CIPHER_SUITES) { + suite_count = LIBWIFI_MAX_CIPHER_SUITES; + } + data += sizeof(suite_count); + if ((((suite_count * sizeof(struct libwifi_cipher_suite)) + data)) > tag_end) { + return -EINVAL; + } + info->num_auth_key_mgmt_suites = suite_count; + + // Iterate through the found Auth Key Management Suites, adding them each time + for (int i = 0; i < suite_count; ++i) { + if (data > tag_end) { + return -EINVAL; + } + cur_cipher_suite = (struct wifi_cipher_suite *) data; + memcpy(&info->auth_key_mgmt_suites[i], cur_cipher_suite, sizeof(struct libwifi_cipher_suite)); + info->auth_key_mgmt_suites[i].suite_type = info->auth_key_mgmt_suites[i].suite_type; + data += sizeof(struct libwifi_cipher_suite); + } + + return 0; +} + +/** + * Similarly to libwifi_enumerate_wpa_suites, this function will enumerate over a supplied + * struct libwifi_wpa_info and write the following into a supplied struct libwifi_bss: + * + * - Multicast Cipher Suite + * - Up to 3 Unicast Cipher Suites + * - Up to 3 Auth Key Management Suites + * + * The bss->encryption_info field is a 64-bit wide bitmask. The larger length is + * required to accomodate the different types of cipher suites without having + * any overlap between group cipher and pairwise cipher. + */ +void libwifi_enumerate_wpa_suites(struct libwifi_wpa_info *wpa_info, struct libwifi_bss *bss) { + switch (wpa_info->multicast_cipher_suite.suite_type) { + case CIPHER_SUITE_WEP40: + bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_WEP40; + break; + case CIPHER_SUITE_WEP104: + bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_WEP104; + break; + case CIPHER_SUITE_TKIP: + bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_TKIP; + break; + case CIPHER_SUITE_RESERVED: + bss->encryption_info |= LIBWIFI_GROUP_CIPHER_SUITE_RESERVED; + break; + default: + break; + } + + for (int i = 0; i < wpa_info->num_unicast_cipher_suites; ++i) { + if ((memcmp(wpa_info->unicast_cipher_suites[i].oui, MICROSOFT_OUI, 3) == 0)) { + switch (wpa_info->unicast_cipher_suites[i].suite_type) { + case CIPHER_SUITE_GROUP: + bss->encryption_info |= LIBWIFI_PAIRWISE_SUITE_GROUP; + break; + case CIPHER_SUITE_TKIP: + bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_TKIP; + break; + case CIPHER_SUITE_RESERVED: + bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_RESERVED; + break; + case CIPHER_SUITE_WEP40: + bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_WEP40; + break; + case CIPHER_SUITE_WEP104: + bss->encryption_info |= LIBWIFI_PAIRWISE_CIPHER_SUITE_WEP104; + break; + default: + break; + } + } + } + + for (int i = 0; i < wpa_info->num_auth_key_mgmt_suites; ++i) { + if (memcmp(wpa_info->auth_key_mgmt_suites[i].oui, MICROSOFT_OUI, 3) == 0) { + switch (wpa_info->auth_key_mgmt_suites[i].suite_type) { + case AKM_SUITE_RESERVED: + bss->encryption_info |= WPA; + bss->encryption_info |= LIBWIFI_AKM_SUITE_RESERVED; + break; + case AKM_SUITE_1X: + bss->encryption_info |= WPA; + bss->encryption_info |= LIBWIFI_AKM_SUITE_1X; + break; + case AKM_SUITE_PSK: + bss->encryption_info |= WPA; + bss->encryption_info |= LIBWIFI_AKM_SUITE_PSK; + break; + case AKM_SUITE_1X_FT: + bss->encryption_info |= WPA; + bss->encryption_info |= LIBWIFI_AKM_SUITE_1X_FT; + break; + case AKM_SUITE_PSK_FT: + bss->encryption_info |= WPA; + bss->encryption_info |= LIBWIFI_AKM_SUITE_PSK_FT; + break; + } + } + } +} + +void libwifi_get_security_type(struct libwifi_bss *bss, char *buf) { + memset(buf, 0, LIBWIFI_SECURITY_BUF_LEN); + + int offset = 0; + int append = 0; + + if (bss->encryption_info == 0) { + snprintf(buf, LIBWIFI_SECURITY_BUF_LEN, "None"); + return; + } + + if (bss->encryption_info & WPA3) { + _libwifi_add_sec_item(buf, &offset, &append, "WPA3"); + } + if (bss->encryption_info & WPA2) { + _libwifi_add_sec_item(buf, &offset, &append, "WPA2"); + } + if (bss->encryption_info & WPA) { + _libwifi_add_sec_item(buf, &offset, &append, "WPA"); + } + if (bss->encryption_info & WEP) { + _libwifi_add_sec_item(buf, &offset, &append, "WEP"); + } +} + +void libwifi_get_group_ciphers(struct libwifi_bss *bss, char *buf) { + memset(buf, 0, LIBWIFI_SECURITY_BUF_LEN); + + int offset = 0; + int append = 0; + + if (bss->encryption_info == 0) { + snprintf(buf + offset, LIBWIFI_SECURITY_BUF_LEN, "None"); + return; + } + + if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_WEP40) { + _libwifi_add_sec_item(buf, &offset, &append, "WEP40"); + } + if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_TKIP) { + _libwifi_add_sec_item(buf, &offset, &append, "TKIP"); + } + if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_RESERVED) { + _libwifi_add_sec_item(buf, &offset, &append, "RESERVED"); + } + if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_CCMP128) { + _libwifi_add_sec_item(buf, &offset, &append, "CCMP128"); + } + if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_WEP104) { + _libwifi_add_sec_item(buf, &offset, &append, "WEP104"); + } + if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_BIP_CMAC128) { + _libwifi_add_sec_item(buf, &offset, &append, "BIP_CMAC128"); + } + if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_NOTALLOWED) { + _libwifi_add_sec_item(buf, &offset, &append, "NOT_ALLOWED"); + } + if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_GCMP128) { + _libwifi_add_sec_item(buf, &offset, &append, "GCMP128"); + } + if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_GCMP256) { + _libwifi_add_sec_item(buf, &offset, &append, "GCMP256"); + } + if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_CCMP256) { + _libwifi_add_sec_item(buf, &offset, &append, "CCMP256"); + } + if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_BIP_GMAC128) { + _libwifi_add_sec_item(buf, &offset, &append, "BIP_GMAC128"); + } + if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_BIP_GMAC256) { + _libwifi_add_sec_item(buf, &offset, &append, "BIP_GMAC256"); + } + if (bss->encryption_info & LIBWIFI_GROUP_CIPHER_SUITE_BIP_CMAC256) { + _libwifi_add_sec_item(buf, &offset, &append, "BIP_CMAC256"); + } +} + +void libwifi_get_pairwise_ciphers(struct libwifi_bss *bss, char *buf) { + memset(buf, 0, LIBWIFI_SECURITY_BUF_LEN); + + int offset = 0; + int append = 0; + + if (bss->encryption_info == 0) { + snprintf(buf + offset, LIBWIFI_SECURITY_BUF_LEN, "None"); + return; + } + + if (bss->encryption_info & LIBWIFI_PAIRWISE_SUITE_GROUP) { + _libwifi_add_sec_item(buf, &offset, &append, "GROUP"); + } + if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_WEP40) { + _libwifi_add_sec_item(buf, &offset, &append, "WEP40"); + } + if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_TKIP) { + _libwifi_add_sec_item(buf, &offset, &append, "TKIP"); + } + if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_RESERVED) { + _libwifi_add_sec_item(buf, &offset, &append, "RESERVED"); + } + if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_CCMP128) { + _libwifi_add_sec_item(buf, &offset, &append, "CCMP128"); + } + if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_WEP104) { + _libwifi_add_sec_item(buf, &offset, &append, "WEP104"); + } + if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_CMAC128) { + _libwifi_add_sec_item(buf, &offset, &append, "BIP_CMAC128"); + } + if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_NOTALLOWED) { + _libwifi_add_sec_item(buf, &offset, &append, "NOT_ALLOWED"); + } + if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_GCMP128) { + _libwifi_add_sec_item(buf, &offset, &append, "GCMP128"); + } + if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_GCMP256) { + _libwifi_add_sec_item(buf, &offset, &append, "GCMP256"); + } + if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_CCMP256) { + _libwifi_add_sec_item(buf, &offset, &append, "CCMP256"); + } + if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_GMAC128) { + _libwifi_add_sec_item(buf, &offset, &append, "BIP_GMAC128"); + } + if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_GMAC256) { + _libwifi_add_sec_item(buf, &offset, &append, "BIP_GMAC256"); + } + if (bss->encryption_info & LIBWIFI_PAIRWISE_CIPHER_SUITE_BIP_CMAC256) { + _libwifi_add_sec_item(buf, &offset, &append, "BIP_CMAC256"); + } +} + +void libwifi_get_auth_key_suites(struct libwifi_bss *bss, char *buf) { + memset(buf, 0, LIBWIFI_SECURITY_BUF_LEN); + + int offset = 0; + int append = 0; + + if (bss->encryption_info == 0) { + snprintf(buf + offset, LIBWIFI_SECURITY_BUF_LEN, "None"); + return; + } + + if (bss->encryption_info & LIBWIFI_AKM_SUITE_RESERVED) { + _libwifi_add_sec_item(buf, &offset, &append, "RESERVED"); + } + if (bss->encryption_info & LIBWIFI_AKM_SUITE_1X) { + _libwifi_add_sec_item(buf, &offset, &append, "802.1X"); + } + if (bss->encryption_info & LIBWIFI_AKM_SUITE_PSK) { + _libwifi_add_sec_item(buf, &offset, &append, "PSK"); + } + if (bss->encryption_info & LIBWIFI_AKM_SUITE_1X_FT) { + _libwifi_add_sec_item(buf, &offset, &append, "802.1X_FT"); + } + if (bss->encryption_info & LIBWIFI_AKM_SUITE_PSK_FT) { + _libwifi_add_sec_item(buf, &offset, &append, "PSK_FT"); + } + if (bss->encryption_info & LIBWIFI_AKM_SUITE_1X_SHA256) { + _libwifi_add_sec_item(buf, &offset, &append, "802.1X_SHA256"); + } + if (bss->encryption_info & LIBWIFI_AKM_SUITE_PSK_SHA256) { + _libwifi_add_sec_item(buf, &offset, &append, "PSK_SHA256"); + } + if (bss->encryption_info & LIBWIFI_AKM_SUITE_TDLS) { + _libwifi_add_sec_item(buf, &offset, &append, "TDLS"); + } + if (bss->encryption_info & LIBWIFI_AKM_SUITE_SAE) { + _libwifi_add_sec_item(buf, &offset, &append, "SAE"); + } + if (bss->encryption_info & LIBWIFI_AKM_SUITE_SAE_FT) { + _libwifi_add_sec_item(buf, &offset, &append, "SAE_FT"); + } + if (bss->encryption_info & LIBWIFI_AKM_SUITE_AP_PEER) { + _libwifi_add_sec_item(buf, &offset, &append, "AP_PEER"); + } + if (bss->encryption_info & LIBWIFI_AKM_SUITE_1X_SUITEB_SHA256) { + _libwifi_add_sec_item(buf, &offset, &append, "802.1X_SUITEB_SHA256"); + } + if (bss->encryption_info & LIBWIFI_AKM_SUITE_1X_SUITEB_SHA384) { + _libwifi_add_sec_item(buf, &offset, &append, "802.1X_SUITEB_SHA384"); + } + if (bss->encryption_info & LIBWIFI_AKM_SUITE_1X_FT_SHA384) { + _libwifi_add_sec_item(buf, &offset, &append, "802.1X_FT_SHA384"); + } + if (bss->encryption_info & LIBWIFI_AKM_SUITE_FILS_SHA256) { + _libwifi_add_sec_item(buf, &offset, &append, "FILS_SHA256"); + } + if (bss->encryption_info & LIBWIFI_AKM_SUITE_FILS_SHA384) { + _libwifi_add_sec_item(buf, &offset, &append, "FILS_SHA384"); + } + if (bss->encryption_info & LIBWIFI_AKM_SUITE_FILS_SHA256_FT) { + _libwifi_add_sec_item(buf, &offset, &append, "FILS_SHA256_FT"); + } + if (bss->encryption_info & LIBWIFI_AKM_SUITE_FILS_SHA384_FT) { + _libwifi_add_sec_item(buf, &offset, &append, "FILS_SHA384_FT"); + } + if (bss->encryption_info & LIBWIFI_AKM_SUITE_OWE) { + _libwifi_add_sec_item(buf, &offset, &append, "OWE"); + } + if (bss->encryption_info & LIBWIFI_AKM_PSK_SHA384_FT) { + _libwifi_add_sec_item(buf, &offset, &append, "PSK_SHA384_FT"); + } + if (bss->encryption_info & LIBWIFI_AKM_PSK_SHA384) { + _libwifi_add_sec_item(buf, &offset, &append, "PSK_SHA384"); + } +} + +void _libwifi_add_sec_item(char *buf, int *offset, int *append, char *item) { + if (*append) { + snprintf(buf + *offset, LIBWIFI_SECURITY_BUF_LEN, ", "); + *offset += strlen(", "); + } + snprintf(buf + *offset, LIBWIFI_SECURITY_BUF_LEN, "%s", item); + *offset += strlen(item); + *append = 1; +} 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 @@ +/* Copyright 2021 The libwifi Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef LIBWIFI_PARSE_SECURITY_H +#define LIBWIFI_PARSE_SECURITY_H + +#include "../../core/frame/management/common.h" +#include "../../core/misc/security.h" + +#include + +#define LIBWIFI_SECURITY_BUF_LEN 256 + +/** + * Get the RSN related information and store it in a + * libwifi_rsn_info. This function will detect and enumerate + * cipher suites, and AKM suites, and the RSN capabilities + * from a specified RSN IE. + * + * @param info A libwifi_rsn_info + * @param tag_data An RSN IE tag + * @param tag_end The end of the specified RSN IE tag + * @return + */ +int libwifi_get_rsn_info(struct libwifi_rsn_info *info, const unsigned char *tag_data, + const unsigned char *tag_end); + +/** + * Enumerate the RSN cipher suites in a libwifi_rsn_info. + * + * This function can be used to fill a libwifi_bss struct + * with information related to the cipher suites and AKM suites + * in the specified libwifi_rsn_info. + * + * @param rsn_info A libwifi_rsn_info + * @param libwifi_bss A libwifi_bss + */ +void libwifi_enumerate_rsn_suites(struct libwifi_rsn_info *rsn_info, struct libwifi_bss *bss); + +/** + * Get the WPA related information and store it in a + * libwifi_wpa_info. This function will detect and enumerate + * cipher suites and AKM suites from a specified WPA IE. + * + * @param info A libwifi_wpa_info + * @param tag_data A WPA IE tag + * @param tag_end The end of the specified WPA IE tag + * @return + */ +int libwifi_get_wpa_info(struct libwifi_wpa_info *info, const unsigned char *tag_data, + const unsigned char *tag_end); + +/** + * Enumerate the WPA cipher suites in a libwifi_wpa_info. + * + * This function can be used to fill a libwifi_bss struct + * with information related to the cipher suites and AKM suites + * in the specified libwifi_wpa_info. + * + * @param wpa_info A libwifi_wpa_info + * @param libwifi_bss A libwifi_bss + */ +void libwifi_enumerate_wpa_suites(struct libwifi_wpa_info *wpa_info, struct libwifi_bss *bss); + +/** + * Enumerate the security types (WEP, WPA, WPA2, WPA3, etc) in a given libwifi_bss, + * formatted into the given buffer. + * + * @param bss A libwifi_bss struct + * @param buf A buffer of length LIBWIFI_SECURITY_BUF_LEN + */ +void libwifi_get_security_type(struct libwifi_bss *bss, char *buf); + +/** + * Enumerate the group ciphers (CCMP, GCMP128, etc) in a given libwifi_bss, + * formatted into the given buffer. + * + * @param bss A libwifi_bss struct + * @param buf A buffer of length LIBWIFI_SECURITY_BUF_LEN + */ +void libwifi_get_group_ciphers(struct libwifi_bss *bss, char *buf); + +/** + * Enumerate the pairwise ciphers (GROUP, CCMP, BIP_CMAC128, etc) in a given libwifi_bss, + * formatted into the given buffer. + * + * @param bss A libwifi_bss struct + * @param buf A buffer of length LIBWIFI_SECURITY_BUF_LEN + */ +void libwifi_get_pairwise_ciphers(struct libwifi_bss *bss, char *buf); + +/** + * Enumerate the auth key management suites in a given libwifi_bss, + * formatted into the given buffer. + * + * @param bss A libwifi_bss struct + * @param buf A buffer of length LIBWIFI_SECURITY_BUF_LEN + */ +void libwifi_get_auth_key_suites(struct libwifi_bss *bss, char *buf); + +/** + * Internal function for adding a formatted string to a buffer for use with + * libwifi_get_* security functions. + * + * @param buf A buffer of length LIBWIFI_SECURITY_BUF_LEN + * @param offset A pointer to the current buffer offset variable + * @param append A pointer to the append state variable + * @param item A pointer to the string to append to the given buf + */ +void _libwifi_add_sec_item(char *buf, int *offset, int *append, char *item); + +#endif /* LIBWIFI_PARSE_SECURITY_H */ -- cgit 1.4.1