From 7c2b373bf37186fd94fdc1d46393780e46f646a8 Mon Sep 17 00:00:00 2001 From: Marc Date: Sat, 10 Sep 2022 20:18:18 +0100 Subject: core/parse: Better handling of Radiotap information Radiotap information is now stored in the `libwifi_frame` struct, and will be kept automatically in `libwifi_frame.radiotap_info` for the lifecycle of said frame, if it is present. A new flag has been added for the frame for use with `libwifi_frame.flags` to detect if the radiotap info is present: `LIBWIFI_FLAGS_RADIOTAP_PRESENT`. The frame parser will now automatically calculate the band and center channel from radiotap data, and will store them in `libwifi_radiotap_info.channel.center` and `libwifi_radiotap_info.channel.band`. Four new flags have been added for use with the new radiotap band field: - `LIBWIFI_RADIOTAP_BAND_2GHZ` - `LIBWIFI_RADIOTAP_BAND_5GHZ` - `LIBWIFI_RADIOTAP_BAND_6GHZ` - `LIBWIFI_RADIOTAP_BAND_900MHZ` These can be used with a binary AND: `if (rtap.channel.band & LIBWIFI_RADIOTAP_BAND_6GHZ) { }` --- src/libwifi/core/frame/frame.c | 8 ++++++-- src/libwifi/core/frame/frame.h | 3 +++ src/libwifi/core/misc/radiotap.h | 11 ++++++++++- src/libwifi/parse/misc/radiotap.c | 17 +++++++++++++++++ 4 files changed, 36 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/libwifi/core/frame/frame.c b/src/libwifi/core/frame/frame.c index c8b6816..99f7fdc 100644 --- a/src/libwifi/core/frame/frame.c +++ b/src/libwifi/core/frame/frame.c @@ -32,8 +32,7 @@ * - QoS Data Frames * - Control Frames */ -int libwifi_get_wifi_frame(struct libwifi_frame *fi, const unsigned char *frame, size_t frame_len, - int radiotap) { +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; @@ -55,6 +54,10 @@ int libwifi_get_wifi_frame(struct libwifi_frame *fi, const unsigned char *frame, fi->flags |= LIBWIFI_FLAGS_FCS_PRESENT; frame_data_len -= sizeof(uint32_t); // FCS is 4 bytes wide } + + fi->flags |= LIBWIFI_FLAGS_RADIOTAP_PRESENT; + fi->radiotap_info = malloc(sizeof(struct libwifi_radiotap_info)); + memcpy(fi->radiotap_info, &rtap_info, sizeof(struct libwifi_radiotap_info)); } struct libwifi_frame_ctrl *frame_control = (struct libwifi_frame_ctrl *) frame_data; @@ -134,5 +137,6 @@ int libwifi_get_wifi_frame(struct libwifi_frame *fi, const unsigned char *frame, } void libwifi_free_wifi_frame(struct libwifi_frame *fi) { + free(fi->radiotap_info); free(fi->body); } diff --git a/src/libwifi/core/frame/frame.h b/src/libwifi/core/frame/frame.h index 5d44dbe..f775479 100644 --- a/src/libwifi/core/frame/frame.h +++ b/src/libwifi/core/frame/frame.h @@ -17,6 +17,7 @@ #define LIBWIFI_CORE_FRAME_H #include "../../core/misc/byteswap.h" +#include "../../core/misc/radiotap.h" #include #include @@ -25,6 +26,7 @@ #define LIBWIFI_FLAGS_FCS_PRESENT (1 << 0) #define LIBWIFI_FLAGS_IS_QOS (1 << 1) #define LIBWIFI_FLAGS_IS_ORDERED (1 << 2) +#define LIBWIFI_FLAGS_RADIOTAP_PRESENT (1 << 3) /* Defined frame types and sub-types */ enum libwifi_frame_type { @@ -306,6 +308,7 @@ union libwifi_mgmt_frame_header { * frame in libwifi. */ struct libwifi_frame { + struct libwifi_radiotap_info *radiotap_info; uint16_t flags; struct libwifi_frame_ctrl frame_control; size_t len; diff --git a/src/libwifi/core/misc/radiotap.h b/src/libwifi/core/misc/radiotap.h index 85ed7b8..f6704e8 100644 --- a/src/libwifi/core/misc/radiotap.h +++ b/src/libwifi/core/misc/radiotap.h @@ -21,13 +21,22 @@ #define LIBWIFI_MAX_RADIOTAP_LEN 128 #define LIBWIFI_MAX_RADIOTAP_ANTENNAS 16 +#define LIBWIFI_RADIOTAP_BAND_2GHZ (1 << 0) +#define LIBWIFI_RADIOTAP_BAND_5GHZ (1 << 1) +#define LIBWIFI_RADIOTAP_BAND_6GHZ (1 << 2) +#define LIBWIFI_RADIOTAP_BAND_900MHZ (1 << 3) + /** * A channel field in radiotap consists of a 2-byte wide flags - * sub-field and a 2-byte wide frequency field + * sub-field and a 2-byte wide frequency field. + * + * libwifi will also calculate the band and center channel. */ struct libwifi_radiotap_channel { uint16_t flags; uint16_t freq; + uint8_t center; + uint8_t band; } __attribute__((packed)); /** diff --git a/src/libwifi/parse/misc/radiotap.c b/src/libwifi/parse/misc/radiotap.c index faf6009..9bf6b54 100644 --- a/src/libwifi/parse/misc/radiotap.c +++ b/src/libwifi/parse/misc/radiotap.c @@ -47,6 +47,23 @@ int libwifi_parse_radiotap_info(struct libwifi_radiotap_info *info, const unsign case IEEE80211_RADIOTAP_CHANNEL: info->channel.freq = le16toh(*(uint16_t *) it.this_arg); info->channel.flags = le16toh(*(uint16_t *) (it.this_arg + 2)); + + // Handle band and channel + if (info->channel.freq >= 2412 && info->channel.freq <= 2484) { + info->channel.band |= LIBWIFI_RADIOTAP_BAND_2GHZ; + if (info->channel.freq == 2484) { + info->channel.center = 14; + } else { + info->channel.center = (info->channel.freq - 2407) / 5; + } + } else if (info->channel.freq >= 5160 && info->channel.freq <= 5885) { + info->channel.band |= LIBWIFI_RADIOTAP_BAND_5GHZ; + info->channel.center = (info->channel.freq - 5000) / 5; + } else if (info->channel.freq >= 5955 && info->channel.freq <= 7115) { + info->channel.band |= LIBWIFI_RADIOTAP_BAND_6GHZ; + info->channel.center = (info->channel.freq - 5950) / 5; + } + break; case IEEE80211_RADIOTAP_RATE: info->rate_raw = *it.this_arg; -- cgit 1.4.1 From 20898787fc8eb98cac50ddeb68a6a44f6769a064 Mon Sep 17 00:00:00 2001 From: Marc Date: Sat, 10 Sep 2022 20:27:14 +0100 Subject: core/parse: Add skeleton for element extension parsing --- src/libwifi/core/frame/tag.h | 7 +++++++ src/libwifi/parse/management/common.c | 11 +++++++++++ 2 files changed, 18 insertions(+) (limited to 'src') diff --git a/src/libwifi/core/frame/tag.h b/src/libwifi/core/frame/tag.h index e435061..b914c77 100644 --- a/src/libwifi/core/frame/tag.h +++ b/src/libwifi/core/frame/tag.h @@ -244,6 +244,13 @@ struct libwifi_tag_vendor_header { int8_t type; } __attribute__((packed)); +/* + * Element extension tagged parameters have a tag number + */ +struct libwifi_tag_extension_header { + uint8_t tag_num; +} __attribute__((packed)); + /** * Add a tagged parameter to a list of frame tagged parameters. * diff --git a/src/libwifi/parse/management/common.c b/src/libwifi/parse/management/common.c index 5e4fbf6..1faaf81 100644 --- a/src/libwifi/parse/management/common.c +++ b/src/libwifi/parse/management/common.c @@ -142,6 +142,7 @@ int libwifi_bss_handle_msft_tag(struct libwifi_bss *bss, const unsigned char *ms */ int libwifi_bss_tag_parser(struct libwifi_bss *bss, struct libwifi_tag_iterator *it) { struct libwifi_tag_vendor_header *vendor_header = NULL; + struct libwifi_tag_extension_header *extension_header = NULL; do { switch (it->tag_header->tag_num) { @@ -166,6 +167,16 @@ int libwifi_bss_tag_parser(struct libwifi_bss *bss, struct libwifi_tag_iterator return -EINVAL; } } + break; + case TAG_ELEMENT_EXTENSION: + extension_header = (struct libwifi_tag_extension_header *) it->tag_data; + + switch (extension_header->tag_num) { + default: + /* Not Implemented */ + break; + } + break; } } while (libwifi_tag_iterator_next(it) != -1); -- cgit 1.4.1 From 91db28425f34c11e0b2a0537f76c8511d239d27a Mon Sep 17 00:00:00 2001 From: Marc Date: Sat, 10 Sep 2022 21:24:59 +0100 Subject: parse: Add clarifying comment for Beacon frame length check --- src/libwifi/parse/management/beacon.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/libwifi/parse/management/beacon.c b/src/libwifi/parse/management/beacon.c index 72246af..3d2feba 100644 --- a/src/libwifi/parse/management/beacon.c +++ b/src/libwifi/parse/management/beacon.c @@ -61,6 +61,7 @@ int libwifi_parse_beacon(struct libwifi_bss *bss, struct libwifi_frame *frame) { } // At least one Tagged Parameter must be present + // + 2 represents two additional bytes: Tag number and a single byte value if (frame->len < (frame->header_len + sizeof(struct libwifi_beacon_fixed_parameters) + 2)) { return -EINVAL; } -- cgit 1.4.1