mpdu: Add ie sorting utility

IE elements in various management frames are ordered.  This ordering is
outlined in 802.11, Section 9.3.3.  The ordering is actually different
depending on the frame type.  Instead of trying to implement the order
manually, add a utility function that will sort the IEs in the order
expected by the particular management frame type.

Since we already have IE ordering look up tables in the various
management frame type validation functions, move them to global level
and re-use these lookup tables for the sorting utility.
This commit is contained in:
Denis Kenzior 2021-08-04 10:41:19 -05:00
parent 9a8129abd6
commit 3f69ddb615
2 changed files with 358 additions and 265 deletions

View File

@ -24,11 +24,274 @@
#include <config.h>
#endif
#include <limits.h>
#include <errno.h>
#include <ell/ell.h>
#include "src/ie.h"
#include "src/mpdu.h"
/* 802.11-2020 section 9.3.3.5 */
static const enum ie_type association_request_ie_order[] = {
IE_TYPE_SSID,
IE_TYPE_SUPPORTED_RATES,
IE_TYPE_EXTENDED_SUPPORTED_RATES,
IE_TYPE_POWER_CAPABILITY,
IE_TYPE_SUPPORTED_CHANNELS,
IE_TYPE_RSN,
IE_TYPE_QOS_CAPABILITY,
IE_TYPE_RM_ENABLED_CAPABILITIES,
IE_TYPE_MOBILITY_DOMAIN,
IE_TYPE_SUPPORTED_OPERATING_CLASSES,
IE_TYPE_HT_CAPABILITIES,
IE_TYPE_BSS_COEXISTENCE,
IE_TYPE_EXTENDED_CAPABILITIES,
IE_TYPE_QOS_TRAFFIC_CAPABILITY,
IE_TYPE_TIM_BROADCAST_REQUEST,
IE_TYPE_INTERWORKING,
IE_TYPE_MULTIBAND,
IE_TYPE_DMG_CAPABILITIES,
IE_TYPE_MULTIPLE_MAC_SUBLAYERS,
IE_TYPE_VHT_CAPABILITIES,
IE_TYPE_OPERATING_MODE_NOTIFICATION,
IE_TYPE_FILS_SESSION,
IE_TYPE_FILS_PUBLIC_KEY,
IE_TYPE_FILS_KEY_CONFIRMATION,
IE_TYPE_FILS_HLP_CONTAINER,
IE_TYPE_FILS_IP_ADDRESS,
IE_TYPE_TWT,
IE_TYPE_AID_REQUEST,
IE_TYPE_S1G_CAPABILITIES,
IE_TYPE_EL_OPERATION,
IE_TYPE_S1G_RELAY,
IE_TYPE_BSS_MAX_IDLE_PERIOD,
IE_TYPE_HEADER_COMPRESSION,
IE_TYPE_MAD,
IE_TYPE_REACHABLE_ADDRESS,
IE_TYPE_S1G_RELAY_ACTIVATION,
IE_TYPE_CDMG_CAPABILITIES,
IE_TYPE_CMMG_CAPABILITIES,
IE_TYPE_GLK_GCR_PARAMETER_SET,
IE_TYPE_FAST_BSS_TRANSITION,
IE_TYPE_RSNX,
IE_TYPE_SUPPLEMENTAL_CLASS_2_CAPABILITIES,
IE_TYPE_MSCS_DESCRIPTOR,
IE_TYPE_VENDOR_SPECIFIC,
};
/* 802.11-2020 section 9.3.3.6 */
static const enum ie_type association_response_ie_order[] = {
IE_TYPE_AID,
IE_TYPE_SUPPORTED_RATES,
IE_TYPE_EXTENDED_SUPPORTED_RATES,
IE_TYPE_EDCA_PARAMETER_SET,
IE_TYPE_RCPI,
IE_TYPE_RSNI,
IE_TYPE_RM_ENABLED_CAPABILITIES,
IE_TYPE_RSN,
IE_TYPE_MOBILITY_DOMAIN,
IE_TYPE_FAST_BSS_TRANSITION,
IE_TYPE_DSE_REGISTERED_LOCATION,
IE_TYPE_TIMEOUT_INTERVAL,
IE_TYPE_HT_CAPABILITIES,
IE_TYPE_HT_OPERATION,
IE_TYPE_BSS_COEXISTENCE,
IE_TYPE_OVERLAPPING_BSS_SCAN_PARAMETERS,
IE_TYPE_EXTENDED_CAPABILITIES,
IE_TYPE_BSS_MAX_IDLE_PERIOD,
IE_TYPE_TIM_BROADCAST_RESPONSE,
IE_TYPE_QOS_MAP_SET,
IE_TYPE_QMF_POLICY,
IE_TYPE_MULTIBAND,
IE_TYPE_DMG_CAPABILITIES,
IE_TYPE_DMG_OPERATION,
IE_TYPE_MULTIPLE_MAC_SUBLAYERS,
IE_TYPE_NEIGHBOR_REPORT,
IE_TYPE_VHT_CAPABILITIES,
IE_TYPE_VHT_OPERATION,
IE_TYPE_OPERATING_MODE_NOTIFICATION,
IE_TYPE_FUTURE_CHANNEL_GUIDANCE,
IE_TYPE_FILS_SESSION,
IE_TYPE_FILS_PUBLIC_KEY,
IE_TYPE_FILS_KEY_CONFIRMATION,
IE_TYPE_FILS_HLP_CONTAINER,
IE_TYPE_FILS_IP_ADDRESS,
IE_TYPE_KEY_DELIVERY,
IE_TYPE_S1G_SECTOR_OPERATION,
IE_TYPE_TWT,
IE_TYPE_TSF_TIMER_ACCURACY,
IE_TYPE_S1G_CAPABILITIES,
IE_TYPE_S1G_OPERATION,
IE_TYPE_AID_RESPONSE,
IE_TYPE_SECTORIZED_GROUP_ID_LIST,
IE_TYPE_S1G_RELAY,
IE_TYPE_HEADER_COMPRESSION,
IE_TYPE_SST_OPERATION,
IE_TYPE_MAD,
IE_TYPE_S1G_RELAY_ACTIVATION,
IE_TYPE_CDMG_CAPABILITIES,
IE_TYPE_CMMG_CAPABILITIES,
IE_TYPE_CMMG_OPERATION,
IE_TYPE_GLK_GCR_PARAMETER_SET,
IE_TYPE_RSNX,
IE_TYPE_MSCS_DESCRIPTOR,
IE_TYPE_VENDOR_SPECIFIC,
};
/* 802.11-2020 section 9.3.3.7 */
static const enum ie_type reassociation_request_ie_order[] = {
IE_TYPE_SSID,
IE_TYPE_SUPPORTED_RATES,
IE_TYPE_EXTENDED_SUPPORTED_RATES,
IE_TYPE_POWER_CAPABILITY,
IE_TYPE_SUPPORTED_CHANNELS,
IE_TYPE_RSN,
IE_TYPE_QOS_CAPABILITY,
IE_TYPE_RM_ENABLED_CAPABILITIES,
IE_TYPE_MOBILITY_DOMAIN,
IE_TYPE_FAST_BSS_TRANSITION,
IE_TYPE_RIC_DATA,
IE_TYPE_SUPPORTED_OPERATING_CLASSES,
IE_TYPE_HT_CAPABILITIES,
IE_TYPE_BSS_COEXISTENCE,
IE_TYPE_EXTENDED_CAPABILITIES,
IE_TYPE_QOS_TRAFFIC_CAPABILITY,
IE_TYPE_TIM_BROADCAST_REQUEST,
IE_TYPE_FMS_REQUEST,
IE_TYPE_DMS_REQUEST,
IE_TYPE_INTERWORKING,
IE_TYPE_MULTIBAND,
IE_TYPE_DMG_CAPABILITIES,
IE_TYPE_MULTIPLE_MAC_SUBLAYERS,
IE_TYPE_VHT_CAPABILITIES,
IE_TYPE_OPERATING_MODE_NOTIFICATION,
IE_TYPE_FILS_SESSION,
IE_TYPE_FILS_PUBLIC_KEY,
IE_TYPE_FILS_KEY_CONFIRMATION,
IE_TYPE_FILS_HLP_CONTAINER,
IE_TYPE_FILS_IP_ADDRESS,
IE_TYPE_TWT,
IE_TYPE_AID_REQUEST,
IE_TYPE_S1G_CAPABILITIES,
IE_TYPE_EL_OPERATION,
IE_TYPE_BSS_MAX_IDLE_PERIOD,
IE_TYPE_S1G_RELAY,
IE_TYPE_HEADER_COMPRESSION,
IE_TYPE_MAD,
IE_TYPE_REACHABLE_ADDRESS,
IE_TYPE_S1G_RELAY_ACTIVATION,
IE_TYPE_CDMG_CAPABILITIES,
IE_TYPE_CMMG_CAPABILITIES,
IE_TYPE_OCI,
IE_TYPE_GLK_GCR_PARAMETER_SET,
IE_TYPE_RSNX,
IE_TYPE_SUPPLEMENTAL_CLASS_2_CAPABILITIES,
IE_TYPE_MSCS_DESCRIPTOR,
IE_TYPE_VENDOR_SPECIFIC,
};
/* 802.11-2020 section 9.3.3.8 */
static const enum ie_type reassociation_response_ie_order[] = {
IE_TYPE_AID,
IE_TYPE_SUPPORTED_RATES,
IE_TYPE_EXTENDED_SUPPORTED_RATES,
IE_TYPE_EDCA_PARAMETER_SET,
IE_TYPE_RCPI,
IE_TYPE_RSNI,
IE_TYPE_RM_ENABLED_CAPABILITIES,
IE_TYPE_RSN,
IE_TYPE_MOBILITY_DOMAIN,
IE_TYPE_FAST_BSS_TRANSITION,
IE_TYPE_RIC_DATA,
IE_TYPE_DSE_REGISTERED_LOCATION,
IE_TYPE_TIMEOUT_INTERVAL,
IE_TYPE_HT_CAPABILITIES,
IE_TYPE_HT_OPERATION,
IE_TYPE_BSS_COEXISTENCE,
IE_TYPE_OVERLAPPING_BSS_SCAN_PARAMETERS,
IE_TYPE_EXTENDED_CAPABILITIES,
IE_TYPE_BSS_MAX_IDLE_PERIOD,
IE_TYPE_TIM_BROADCAST_RESPONSE,
IE_TYPE_FMS_RESPONSE,
IE_TYPE_DMS_RESPONSE,
IE_TYPE_QOS_MAP_SET,
IE_TYPE_QMF_POLICY,
IE_TYPE_MULTIBAND,
IE_TYPE_DMG_CAPABILITIES,
IE_TYPE_DMG_OPERATION,
IE_TYPE_MULTIPLE_MAC_SUBLAYERS,
IE_TYPE_NEIGHBOR_REPORT,
IE_TYPE_VHT_CAPABILITIES,
IE_TYPE_VHT_OPERATION,
IE_TYPE_OPERATING_MODE_NOTIFICATION,
IE_TYPE_FUTURE_CHANNEL_GUIDANCE,
IE_TYPE_FILS_SESSION,
IE_TYPE_FILS_PUBLIC_KEY,
IE_TYPE_FILS_KEY_CONFIRMATION,
IE_TYPE_FILS_HLP_CONTAINER,
IE_TYPE_FILS_IP_ADDRESS,
IE_TYPE_KEY_DELIVERY,
IE_TYPE_S1G_SECTOR_OPERATION,
IE_TYPE_TWT,
IE_TYPE_TSF_TIMER_ACCURACY,
IE_TYPE_S1G_CAPABILITIES,
IE_TYPE_S1G_OPERATION,
IE_TYPE_AID_RESPONSE,
IE_TYPE_SECTORIZED_GROUP_ID_LIST,
IE_TYPE_S1G_RELAY,
IE_TYPE_HEADER_COMPRESSION,
IE_TYPE_SST_OPERATION,
IE_TYPE_MAD,
IE_TYPE_S1G_RELAY_ACTIVATION,
IE_TYPE_CDMG_CAPABILITIES,
IE_TYPE_CMMG_CAPABILITIES,
IE_TYPE_CMMG_OPERATION,
IE_TYPE_OCI,
IE_TYPE_GLK_GCR_PARAMETER_SET,
IE_TYPE_RSNX,
IE_TYPE_MSCS_DESCRIPTOR,
IE_TYPE_VENDOR_SPECIFIC,
};
/* 802.11-2020 section 9.3.3.9 */
static const enum ie_type probe_request_ie_order[] = {
IE_TYPE_SSID,
IE_TYPE_SUPPORTED_RATES,
IE_TYPE_REQUEST,
IE_TYPE_EXTENDED_SUPPORTED_RATES,
IE_TYPE_DSSS_PARAMETER_SET,
IE_TYPE_SUPPORTED_OPERATING_CLASSES,
IE_TYPE_HT_CAPABILITIES,
IE_TYPE_BSS_COEXISTENCE,
IE_TYPE_EXTENDED_CAPABILITIES,
IE_TYPE_SSID_LIST,
IE_TYPE_CHANNEL_USAGE,
IE_TYPE_INTERWORKING,
IE_TYPE_MESH_ID,
IE_TYPE_MULTIBAND,
IE_TYPE_DMG_CAPABILITIES,
IE_TYPE_MULTIPLE_MAC_SUBLAYERS,
IE_TYPE_VHT_CAPABILITIES,
IE_TYPE_ESTIMATED_SERVICE_PARAMETERS,
IE_TYPE_EXTENDED_REQUEST,
IE_TYPE_FILS_REQUEST_PARAMETERS,
IE_TYPE_AP_CSN,
IE_TYPE_CHANGE_SEQUENCE,
IE_TYPE_S1G_RELAY_DISCOVERY,
IE_TYPE_PV1_PROBE_RESPONSE_OPTION,
IE_TYPE_S1G_CAPABILITIES,
IE_TYPE_EL_OPERATION,
IE_TYPE_MAD,
IE_TYPE_VENDOR_SPECIFIC_REQUEST,
IE_TYPE_CDMG_CAPABILITIES,
IE_TYPE_CLUSTER_PROBE,
IE_TYPE_CMMG_CAPABILITIES,
IE_TYPE_ESTIMATED_SERVICE_PARAMETERS_OUT,
IE_TYPE_SUPPLEMENTAL_CLASS_2_CAPABILITIES,
IE_TYPE_VENDOR_SPECIFIC,
};
static bool validate_mgmt_header(const struct mmpdu_header *mpdu,
int len, int *offset)
{
@ -149,335 +412,85 @@ static bool validate_mgmt_ies(const uint8_t *ies, size_t ies_len,
return true;
}
/* 802.11-2020 section 9.3.3.5 */
static bool validate_association_request_mmpdu(const struct mmpdu_header *mpdu,
int len, int *offset)
{
const struct mmpdu_association_request *body =
(const void *) mpdu + *offset;
static const enum ie_type ie_order[] = {
IE_TYPE_SSID,
IE_TYPE_SUPPORTED_RATES,
IE_TYPE_EXTENDED_SUPPORTED_RATES,
IE_TYPE_POWER_CAPABILITY,
IE_TYPE_SUPPORTED_CHANNELS,
IE_TYPE_RSN,
IE_TYPE_QOS_CAPABILITY,
IE_TYPE_RM_ENABLED_CAPABILITIES,
IE_TYPE_MOBILITY_DOMAIN,
IE_TYPE_SUPPORTED_OPERATING_CLASSES,
IE_TYPE_HT_CAPABILITIES,
IE_TYPE_BSS_COEXISTENCE,
IE_TYPE_EXTENDED_CAPABILITIES,
IE_TYPE_QOS_TRAFFIC_CAPABILITY,
IE_TYPE_TIM_BROADCAST_REQUEST,
IE_TYPE_INTERWORKING,
IE_TYPE_MULTIBAND,
IE_TYPE_DMG_CAPABILITIES,
IE_TYPE_MULTIPLE_MAC_SUBLAYERS,
IE_TYPE_VHT_CAPABILITIES,
IE_TYPE_OPERATING_MODE_NOTIFICATION,
IE_TYPE_FILS_SESSION,
IE_TYPE_FILS_PUBLIC_KEY,
IE_TYPE_FILS_KEY_CONFIRMATION,
IE_TYPE_FILS_HLP_CONTAINER,
IE_TYPE_FILS_IP_ADDRESS,
IE_TYPE_TWT,
IE_TYPE_AID_REQUEST,
IE_TYPE_S1G_CAPABILITIES,
IE_TYPE_EL_OPERATION,
IE_TYPE_S1G_RELAY,
IE_TYPE_BSS_MAX_IDLE_PERIOD,
IE_TYPE_HEADER_COMPRESSION,
IE_TYPE_MAD,
IE_TYPE_REACHABLE_ADDRESS,
IE_TYPE_S1G_RELAY_ACTIVATION,
IE_TYPE_CDMG_CAPABILITIES,
IE_TYPE_CMMG_CAPABILITIES,
IE_TYPE_GLK_GCR_PARAMETER_SET,
IE_TYPE_FAST_BSS_TRANSITION,
IE_TYPE_RSNX,
IE_TYPE_SUPPLEMENTAL_CLASS_2_CAPABILITIES,
IE_TYPE_MSCS_DESCRIPTOR,
IE_TYPE_VENDOR_SPECIFIC,
};
if (len < *offset + (int) sizeof(struct mmpdu_association_request))
return false;
*offset += sizeof(struct mmpdu_association_request);
return validate_mgmt_ies(body->ies, len - *offset, ie_order,
L_ARRAY_SIZE(ie_order));
return validate_mgmt_ies(body->ies, len - *offset,
association_request_ie_order,
L_ARRAY_SIZE(association_request_ie_order));
}
/* 802.11-2020 section 9.3.3.6 */
static bool validate_association_response_mmpdu(const struct mmpdu_header *mpdu,
int len, int *offset)
{
const struct mmpdu_association_response *body =
(const void *) mpdu + *offset;
static const enum ie_type ie_order[] = {
IE_TYPE_AID,
IE_TYPE_SUPPORTED_RATES,
IE_TYPE_EXTENDED_SUPPORTED_RATES,
IE_TYPE_EDCA_PARAMETER_SET,
IE_TYPE_RCPI,
IE_TYPE_RSNI,
IE_TYPE_RM_ENABLED_CAPABILITIES,
IE_TYPE_RSN,
IE_TYPE_MOBILITY_DOMAIN,
IE_TYPE_FAST_BSS_TRANSITION,
IE_TYPE_DSE_REGISTERED_LOCATION,
IE_TYPE_TIMEOUT_INTERVAL,
IE_TYPE_HT_CAPABILITIES,
IE_TYPE_HT_OPERATION,
IE_TYPE_BSS_COEXISTENCE,
IE_TYPE_OVERLAPPING_BSS_SCAN_PARAMETERS,
IE_TYPE_EXTENDED_CAPABILITIES,
IE_TYPE_BSS_MAX_IDLE_PERIOD,
IE_TYPE_TIM_BROADCAST_RESPONSE,
IE_TYPE_QOS_MAP_SET,
IE_TYPE_QMF_POLICY,
IE_TYPE_MULTIBAND,
IE_TYPE_DMG_CAPABILITIES,
IE_TYPE_DMG_OPERATION,
IE_TYPE_MULTIPLE_MAC_SUBLAYERS,
IE_TYPE_NEIGHBOR_REPORT,
IE_TYPE_VHT_CAPABILITIES,
IE_TYPE_VHT_OPERATION,
IE_TYPE_OPERATING_MODE_NOTIFICATION,
IE_TYPE_FUTURE_CHANNEL_GUIDANCE,
IE_TYPE_FILS_SESSION,
IE_TYPE_FILS_PUBLIC_KEY,
IE_TYPE_FILS_KEY_CONFIRMATION,
IE_TYPE_FILS_HLP_CONTAINER,
IE_TYPE_FILS_IP_ADDRESS,
IE_TYPE_KEY_DELIVERY,
IE_TYPE_S1G_SECTOR_OPERATION,
IE_TYPE_TWT,
IE_TYPE_TSF_TIMER_ACCURACY,
IE_TYPE_S1G_CAPABILITIES,
IE_TYPE_S1G_OPERATION,
IE_TYPE_AID_RESPONSE,
IE_TYPE_SECTORIZED_GROUP_ID_LIST,
IE_TYPE_S1G_RELAY,
IE_TYPE_HEADER_COMPRESSION,
IE_TYPE_SST_OPERATION,
IE_TYPE_MAD,
IE_TYPE_S1G_RELAY_ACTIVATION,
IE_TYPE_CDMG_CAPABILITIES,
IE_TYPE_CMMG_CAPABILITIES,
IE_TYPE_CMMG_OPERATION,
IE_TYPE_GLK_GCR_PARAMETER_SET,
IE_TYPE_RSNX,
IE_TYPE_MSCS_DESCRIPTOR,
IE_TYPE_VENDOR_SPECIFIC,
};
if (len < *offset + (int) sizeof(struct mmpdu_association_response))
return false;
*offset += sizeof(struct mmpdu_association_response);
return validate_mgmt_ies(body->ies, len - *offset, ie_order,
L_ARRAY_SIZE(ie_order));
return validate_mgmt_ies(body->ies, len - *offset,
association_response_ie_order,
L_ARRAY_SIZE(association_response_ie_order));
}
/* 802.11-2020 section 9.3.3.7 */
static bool validate_reassociation_request_mmpdu(
const struct mmpdu_header *mpdu,
int len, int *offset)
{
const struct mmpdu_reassociation_request *body =
(const void *) mpdu + *offset;
static const enum ie_type ie_order[] = {
IE_TYPE_SSID,
IE_TYPE_SUPPORTED_RATES,
IE_TYPE_EXTENDED_SUPPORTED_RATES,
IE_TYPE_POWER_CAPABILITY,
IE_TYPE_SUPPORTED_CHANNELS,
IE_TYPE_RSN,
IE_TYPE_QOS_CAPABILITY,
IE_TYPE_RM_ENABLED_CAPABILITIES,
IE_TYPE_MOBILITY_DOMAIN,
IE_TYPE_FAST_BSS_TRANSITION,
IE_TYPE_RIC_DATA,
IE_TYPE_SUPPORTED_OPERATING_CLASSES,
IE_TYPE_HT_CAPABILITIES,
IE_TYPE_BSS_COEXISTENCE,
IE_TYPE_EXTENDED_CAPABILITIES,
IE_TYPE_QOS_TRAFFIC_CAPABILITY,
IE_TYPE_TIM_BROADCAST_REQUEST,
IE_TYPE_FMS_REQUEST,
IE_TYPE_DMS_REQUEST,
IE_TYPE_INTERWORKING,
IE_TYPE_MULTIBAND,
IE_TYPE_DMG_CAPABILITIES,
IE_TYPE_MULTIPLE_MAC_SUBLAYERS,
IE_TYPE_VHT_CAPABILITIES,
IE_TYPE_OPERATING_MODE_NOTIFICATION,
IE_TYPE_FILS_SESSION,
IE_TYPE_FILS_PUBLIC_KEY,
IE_TYPE_FILS_KEY_CONFIRMATION,
IE_TYPE_FILS_HLP_CONTAINER,
IE_TYPE_FILS_IP_ADDRESS,
IE_TYPE_TWT,
IE_TYPE_AID_REQUEST,
IE_TYPE_S1G_CAPABILITIES,
IE_TYPE_EL_OPERATION,
IE_TYPE_BSS_MAX_IDLE_PERIOD,
IE_TYPE_S1G_RELAY,
IE_TYPE_HEADER_COMPRESSION,
IE_TYPE_MAD,
IE_TYPE_REACHABLE_ADDRESS,
IE_TYPE_S1G_RELAY_ACTIVATION,
IE_TYPE_CDMG_CAPABILITIES,
IE_TYPE_CMMG_CAPABILITIES,
IE_TYPE_OCI,
IE_TYPE_GLK_GCR_PARAMETER_SET,
IE_TYPE_RSNX,
IE_TYPE_SUPPLEMENTAL_CLASS_2_CAPABILITIES,
IE_TYPE_MSCS_DESCRIPTOR,
IE_TYPE_VENDOR_SPECIFIC,
};
if (len < *offset + (int) sizeof(struct mmpdu_reassociation_request))
return false;
*offset += sizeof(struct mmpdu_reassociation_request);
return validate_mgmt_ies(body->ies, len - *offset, ie_order,
L_ARRAY_SIZE(ie_order));
return validate_mgmt_ies(body->ies, len - *offset,
reassociation_request_ie_order,
L_ARRAY_SIZE(reassociation_request_ie_order));
}
/* 802.11-2020 section 9.3.3.8 */
static bool validate_reassociation_response_mmpdu(
const struct mmpdu_header *mpdu,
int len, int *offset)
{
const struct mmpdu_reassociation_response *body =
(const void *) mpdu + *offset;
static const enum ie_type ie_order[] = {
IE_TYPE_AID,
IE_TYPE_SUPPORTED_RATES,
IE_TYPE_EXTENDED_SUPPORTED_RATES,
IE_TYPE_EDCA_PARAMETER_SET,
IE_TYPE_RCPI,
IE_TYPE_RSNI,
IE_TYPE_RM_ENABLED_CAPABILITIES,
IE_TYPE_RSN,
IE_TYPE_MOBILITY_DOMAIN,
IE_TYPE_FAST_BSS_TRANSITION,
IE_TYPE_RIC_DATA,
IE_TYPE_DSE_REGISTERED_LOCATION,
IE_TYPE_TIMEOUT_INTERVAL,
IE_TYPE_HT_CAPABILITIES,
IE_TYPE_HT_OPERATION,
IE_TYPE_BSS_COEXISTENCE,
IE_TYPE_OVERLAPPING_BSS_SCAN_PARAMETERS,
IE_TYPE_EXTENDED_CAPABILITIES,
IE_TYPE_BSS_MAX_IDLE_PERIOD,
IE_TYPE_TIM_BROADCAST_RESPONSE,
IE_TYPE_FMS_RESPONSE,
IE_TYPE_DMS_RESPONSE,
IE_TYPE_QOS_MAP_SET,
IE_TYPE_QMF_POLICY,
IE_TYPE_MULTIBAND,
IE_TYPE_DMG_CAPABILITIES,
IE_TYPE_DMG_OPERATION,
IE_TYPE_MULTIPLE_MAC_SUBLAYERS,
IE_TYPE_NEIGHBOR_REPORT,
IE_TYPE_VHT_CAPABILITIES,
IE_TYPE_VHT_OPERATION,
IE_TYPE_OPERATING_MODE_NOTIFICATION,
IE_TYPE_FUTURE_CHANNEL_GUIDANCE,
IE_TYPE_FILS_SESSION,
IE_TYPE_FILS_PUBLIC_KEY,
IE_TYPE_FILS_KEY_CONFIRMATION,
IE_TYPE_FILS_HLP_CONTAINER,
IE_TYPE_FILS_IP_ADDRESS,
IE_TYPE_KEY_DELIVERY,
IE_TYPE_S1G_SECTOR_OPERATION,
IE_TYPE_TWT,
IE_TYPE_TSF_TIMER_ACCURACY,
IE_TYPE_S1G_CAPABILITIES,
IE_TYPE_S1G_OPERATION,
IE_TYPE_AID_RESPONSE,
IE_TYPE_SECTORIZED_GROUP_ID_LIST,
IE_TYPE_S1G_RELAY,
IE_TYPE_HEADER_COMPRESSION,
IE_TYPE_SST_OPERATION,
IE_TYPE_MAD,
IE_TYPE_S1G_RELAY_ACTIVATION,
IE_TYPE_CDMG_CAPABILITIES,
IE_TYPE_CMMG_CAPABILITIES,
IE_TYPE_CMMG_OPERATION,
IE_TYPE_OCI,
IE_TYPE_GLK_GCR_PARAMETER_SET,
IE_TYPE_RSNX,
IE_TYPE_MSCS_DESCRIPTOR,
IE_TYPE_VENDOR_SPECIFIC,
};
if (len < *offset + (int) sizeof(struct mmpdu_reassociation_response))
return false;
*offset += sizeof(struct mmpdu_reassociation_response);
return validate_mgmt_ies(body->ies, len - *offset, ie_order,
L_ARRAY_SIZE(ie_order));
return validate_mgmt_ies(body->ies, len - *offset,
reassociation_response_ie_order,
L_ARRAY_SIZE(reassociation_response_ie_order));
}
/* 802.11-2020 section 9.3.3.9 */
static bool validate_probe_request_mmpdu(const struct mmpdu_header *mpdu,
int len, int *offset)
{
const struct mmpdu_probe_request *body = (const void *) mpdu + *offset;
static const enum ie_type ie_order[] = {
IE_TYPE_SSID,
IE_TYPE_SUPPORTED_RATES,
IE_TYPE_REQUEST,
IE_TYPE_EXTENDED_SUPPORTED_RATES,
IE_TYPE_DSSS_PARAMETER_SET,
IE_TYPE_SUPPORTED_OPERATING_CLASSES,
IE_TYPE_HT_CAPABILITIES,
IE_TYPE_BSS_COEXISTENCE,
IE_TYPE_EXTENDED_CAPABILITIES,
IE_TYPE_SSID_LIST,
IE_TYPE_CHANNEL_USAGE,
IE_TYPE_INTERWORKING,
IE_TYPE_MESH_ID,
IE_TYPE_MULTIBAND,
IE_TYPE_DMG_CAPABILITIES,
IE_TYPE_MULTIPLE_MAC_SUBLAYERS,
IE_TYPE_VHT_CAPABILITIES,
IE_TYPE_ESTIMATED_SERVICE_PARAMETERS,
IE_TYPE_EXTENDED_REQUEST,
IE_TYPE_FILS_REQUEST_PARAMETERS,
IE_TYPE_AP_CSN,
IE_TYPE_CHANGE_SEQUENCE,
IE_TYPE_S1G_RELAY_DISCOVERY,
IE_TYPE_PV1_PROBE_RESPONSE_OPTION,
IE_TYPE_S1G_CAPABILITIES,
IE_TYPE_EL_OPERATION,
IE_TYPE_MAD,
IE_TYPE_VENDOR_SPECIFIC_REQUEST,
IE_TYPE_CDMG_CAPABILITIES,
IE_TYPE_CLUSTER_PROBE,
IE_TYPE_CMMG_CAPABILITIES,
IE_TYPE_ESTIMATED_SERVICE_PARAMETERS_OUT,
IE_TYPE_SUPPLEMENTAL_CLASS_2_CAPABILITIES,
IE_TYPE_VENDOR_SPECIFIC,
};
if (len < *offset + (int) sizeof(struct mmpdu_probe_request))
return false;
*offset += sizeof(struct mmpdu_probe_request);
return validate_mgmt_ies(body->ies, len - *offset, ie_order,
L_ARRAY_SIZE(ie_order));
return validate_mgmt_ies(body->ies, len - *offset,
probe_request_ie_order,
L_ARRAY_SIZE(probe_request_ie_order));
}
/* 802.11-2016 section 9.3.3.11 */
@ -782,3 +795,80 @@ const void *mmpdu_body(const struct mmpdu_header *mmpdu)
{
return ((const uint8_t *) mmpdu + mmpdu_header_len(mmpdu));
}
struct ie_sort_info {
const enum ie_type *ie_order;
size_t n_elem;
};
static struct ie_sort_info sortinfo;
static unsigned int ie_order_find(const struct iovec *iov)
{
const uint8_t *ie = iov->iov_base;
enum ie_type type = ie[0];
unsigned int i;
if (ie[0] == IE_TYPE_EXTENSION)
type = 256 + ie[2];
for (i = 0; i < sortinfo.n_elem; i++) {
if (sortinfo.ie_order[i] != type)
continue;
return i;
}
return UINT_MAX;
}
static int ie_order_compare(const void *a, const void *b)
{
const struct iovec *iova = a;
const struct iovec *iovb = b;
unsigned int ia = ie_order_find(iova);
unsigned int ib = ie_order_find(iovb);
if (ia < ib)
return -1;
if (ia > ib)
return 1;
return 0;
}
int mpdu_sort_ies(enum mpdu_management_subtype type,
struct iovec *iov, size_t n_iovs)
{
switch (type) {
case MPDU_MANAGEMENT_SUBTYPE_ASSOCIATION_REQUEST:
sortinfo.ie_order = association_request_ie_order;
sortinfo.n_elem = L_ARRAY_SIZE(association_request_ie_order);
break;
case MPDU_MANAGEMENT_SUBTYPE_ASSOCIATION_RESPONSE:
sortinfo.ie_order = association_response_ie_order;
sortinfo.n_elem = L_ARRAY_SIZE(association_response_ie_order);
break;
case MPDU_MANAGEMENT_SUBTYPE_REASSOCIATION_REQUEST:
sortinfo.ie_order = reassociation_request_ie_order;
sortinfo.n_elem = L_ARRAY_SIZE(reassociation_request_ie_order);
break;
case MPDU_MANAGEMENT_SUBTYPE_REASSOCIATION_RESPONSE:
sortinfo.ie_order = reassociation_response_ie_order;
sortinfo.n_elem = L_ARRAY_SIZE(reassociation_response_ie_order);
break;
case MPDU_MANAGEMENT_SUBTYPE_PROBE_REQUEST:
sortinfo.ie_order = probe_request_ie_order;
sortinfo.n_elem = L_ARRAY_SIZE(probe_request_ie_order);
break;
default:
return -ENOTSUP;
}
/*
* qsort_r would be better, but it is still missing on some non-glibc
* implementations, and since iwd is not multi-threaded, qsort is
* just as good
*/
qsort(iov, n_iovs, sizeof(struct iovec), ie_order_compare);
return 0;
}

View File

@ -411,3 +411,6 @@ struct mmpdu_deauthentication {
const struct mmpdu_header *mpdu_validate(const uint8_t *frame, int len);
const void *mmpdu_body(const struct mmpdu_header *mpdu);
size_t mmpdu_header_len(const struct mmpdu_header *mmpdu);
int mpdu_sort_ies(enum mpdu_management_subtype type,
struct iovec *iov, size_t n_iovs);