2177 lines · 51.2 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0/* * Wireless utility functions * * Copyright 2007-2009	Johannes Berg <johannes@sipsolutions.net> * Copyright 2013-2014  Intel Mobile Communications GmbH * Copyright 2017	Intel Deutschland GmbH * Copyright (C) 2018-2020 Intel Corporation */#include <linux/export.h>#include <linux/bitops.h>#include <linux/etherdevice.h>#include <linux/slab.h>#include <linux/ieee80211.h>#include <net/cfg80211.h>#include <net/ip.h>#include <net/dsfield.h>#include <linux/if_vlan.h>#include <linux/mpls.h>#include <linux/gcd.h>#include <linux/bitfield.h>#include <linux/nospec.h>#include "core.h"#include "rdev-ops.h"  struct ieee80211_rate *ieee80211_get_response_rate(struct ieee80211_supported_band *sband,			    u32 basic_rates, int bitrate){	struct ieee80211_rate *result = &sband->bitrates[0];	int i; 	for (i = 0; i < sband->n_bitrates; i++) {		if (!(basic_rates & BIT(i)))			continue;		if (sband->bitrates[i].bitrate > bitrate)			continue;		result = &sband->bitrates[i];	} 	return result;}EXPORT_SYMBOL(ieee80211_get_response_rate); u32 ieee80211_mandatory_rates(struct ieee80211_supported_band *sband,			      enum nl80211_bss_scan_width scan_width){	struct ieee80211_rate *bitrates;	u32 mandatory_rates = 0;	enum ieee80211_rate_flags mandatory_flag;	int i; 	if (WARN_ON(!sband))		return 1; 	if (sband->band == NL80211_BAND_2GHZ) {		if (scan_width == NL80211_BSS_CHAN_WIDTH_5 ||		    scan_width == NL80211_BSS_CHAN_WIDTH_10)			mandatory_flag = IEEE80211_RATE_MANDATORY_G;		else			mandatory_flag = IEEE80211_RATE_MANDATORY_B;	} else {		mandatory_flag = IEEE80211_RATE_MANDATORY_A;	} 	bitrates = sband->bitrates;	for (i = 0; i < sband->n_bitrates; i++)		if (bitrates[i].flags & mandatory_flag)			mandatory_rates |= BIT(i);	return mandatory_rates;}EXPORT_SYMBOL(ieee80211_mandatory_rates); u32 ieee80211_channel_to_freq_khz(int chan, enum nl80211_band band){	/* see 802.11 17.3.8.3.2 and Annex J	 * there are overlapping channel numbers in 5GHz and 2GHz bands */	if (chan <= 0)		return 0; /* not supported */	switch (band) {	case NL80211_BAND_2GHZ:		if (chan == 14)			return MHZ_TO_KHZ(2484);		else if (chan < 14)			return MHZ_TO_KHZ(2407 + chan * 5);		break;	case NL80211_BAND_5GHZ:		if (chan >= 182 && chan <= 196)			return MHZ_TO_KHZ(4000 + chan * 5);		else			return MHZ_TO_KHZ(5000 + chan * 5);		break;	case NL80211_BAND_6GHZ:		/* see 802.11ax D6.1 27.3.23.2 */		if (chan == 2)			return MHZ_TO_KHZ(5935);		if (chan <= 253)			return MHZ_TO_KHZ(5950 + chan * 5);		break;	case NL80211_BAND_60GHZ:		if (chan < 7)			return MHZ_TO_KHZ(56160 + chan * 2160);		break;	case NL80211_BAND_S1GHZ:		return 902000 + chan * 500;	default:		;	}	return 0; /* not supported */}EXPORT_SYMBOL(ieee80211_channel_to_freq_khz); int ieee80211_freq_khz_to_channel(u32 freq){	/* TODO: just handle MHz for now */	freq = KHZ_TO_MHZ(freq); 	/* see 802.11 17.3.8.3.2 and Annex J */	if (freq == 2484)		return 14;	else if (freq < 2484)		return (freq - 2407) / 5;	else if (freq >= 4910 && freq <= 4980)		return (freq - 4000) / 5;	else if (freq < 5945)		return (freq - 5000) / 5;	else if (freq <= 45000) /* DMG band lower limit */		/* see 802.11ax D4.1 27.3.22.2 */		return (freq - 5940) / 5;	else if (freq >= 58320 && freq <= 70200)		return (freq - 56160) / 2160;	else		return 0;}EXPORT_SYMBOL(ieee80211_freq_khz_to_channel); struct ieee80211_channel *ieee80211_get_channel_khz(struct wiphy *wiphy,						    u32 freq){	enum nl80211_band band;	struct ieee80211_supported_band *sband;	int i; 	for (band = 0; band < NUM_NL80211_BANDS; band++) {		sband = wiphy->bands[band]; 		if (!sband)			continue; 		for (i = 0; i < sband->n_channels; i++) {			struct ieee80211_channel *chan = &sband->channels[i]; 			if (ieee80211_channel_to_khz(chan) == freq)				return chan;		}	} 	return NULL;}EXPORT_SYMBOL(ieee80211_get_channel_khz); static void set_mandatory_flags_band(struct ieee80211_supported_band *sband){	int i, want; 	switch (sband->band) {	case NL80211_BAND_5GHZ:	case NL80211_BAND_6GHZ:		want = 3;		for (i = 0; i < sband->n_bitrates; i++) {			if (sband->bitrates[i].bitrate == 60 ||			    sband->bitrates[i].bitrate == 120 ||			    sband->bitrates[i].bitrate == 240) {				sband->bitrates[i].flags |=					IEEE80211_RATE_MANDATORY_A;				want--;			}		}		WARN_ON(want);		break;	case NL80211_BAND_2GHZ:		want = 7;		for (i = 0; i < sband->n_bitrates; i++) {			switch (sband->bitrates[i].bitrate) {			case 10:			case 20:			case 55:			case 110:				sband->bitrates[i].flags |=					IEEE80211_RATE_MANDATORY_B |					IEEE80211_RATE_MANDATORY_G;				want--;				break;			case 60:			case 120:			case 240:				sband->bitrates[i].flags |=					IEEE80211_RATE_MANDATORY_G;				want--;				/* fall through */			default:				sband->bitrates[i].flags |=					IEEE80211_RATE_ERP_G;				break;			}		}		WARN_ON(want != 0 && want != 3);		break;	case NL80211_BAND_60GHZ:		/* check for mandatory HT MCS 1..4 */		WARN_ON(!sband->ht_cap.ht_supported);		WARN_ON((sband->ht_cap.mcs.rx_mask[0] & 0x1e) != 0x1e);		break;	case NL80211_BAND_S1GHZ:		/* Figure 9-589bd: 3 means unsupported, so != 3 means at least		 * mandatory is ok.		 */		WARN_ON((sband->s1g_cap.nss_mcs[0] & 0x3) == 0x3);		break;	case NUM_NL80211_BANDS:	default:		WARN_ON(1);		break;	}} void ieee80211_set_bitrate_flags(struct wiphy *wiphy){	enum nl80211_band band; 	for (band = 0; band < NUM_NL80211_BANDS; band++)		if (wiphy->bands[band])			set_mandatory_flags_band(wiphy->bands[band]);} bool cfg80211_supported_cipher_suite(struct wiphy *wiphy, u32 cipher){	int i;	for (i = 0; i < wiphy->n_cipher_suites; i++)		if (cipher == wiphy->cipher_suites[i])			return true;	return false;} int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev,				   struct key_params *params, int key_idx,				   bool pairwise, const u8 *mac_addr){	int max_key_idx = 5; 	if (wiphy_ext_feature_isset(&rdev->wiphy,				    NL80211_EXT_FEATURE_BEACON_PROTECTION) ||	    wiphy_ext_feature_isset(&rdev->wiphy,				    NL80211_EXT_FEATURE_BEACON_PROTECTION_CLIENT))		max_key_idx = 7;	if (key_idx < 0 || key_idx > max_key_idx)		return -EINVAL; 	if (!pairwise && mac_addr && !(rdev->wiphy.flags & WIPHY_FLAG_IBSS_RSN))		return -EINVAL; 	if (pairwise && !mac_addr)		return -EINVAL; 	switch (params->cipher) {	case WLAN_CIPHER_SUITE_TKIP:		/* Extended Key ID can only be used with CCMP/GCMP ciphers */		if ((pairwise && key_idx) ||		    params->mode != NL80211_KEY_RX_TX)			return -EINVAL;		break;	case WLAN_CIPHER_SUITE_CCMP:	case WLAN_CIPHER_SUITE_CCMP_256:	case WLAN_CIPHER_SUITE_GCMP:	case WLAN_CIPHER_SUITE_GCMP_256:		/* IEEE802.11-2016 allows only 0 and - when supporting		 * Extended Key ID - 1 as index for pairwise keys.		 * @NL80211_KEY_NO_TX is only allowed for pairwise keys when		 * the driver supports Extended Key ID.		 * @NL80211_KEY_SET_TX can't be set when installing and		 * validating a key.		 */		if ((params->mode == NL80211_KEY_NO_TX && !pairwise) ||		    params->mode == NL80211_KEY_SET_TX)			return -EINVAL;		if (wiphy_ext_feature_isset(&rdev->wiphy,					    NL80211_EXT_FEATURE_EXT_KEY_ID)) {			if (pairwise && (key_idx < 0 || key_idx > 1))				return -EINVAL;		} else if (pairwise && key_idx) {			return -EINVAL;		}		break;	case WLAN_CIPHER_SUITE_AES_CMAC:	case WLAN_CIPHER_SUITE_BIP_CMAC_256:	case WLAN_CIPHER_SUITE_BIP_GMAC_128:	case WLAN_CIPHER_SUITE_BIP_GMAC_256:		/* Disallow BIP (group-only) cipher as pairwise cipher */		if (pairwise)			return -EINVAL;		if (key_idx < 4)			return -EINVAL;		break;	case WLAN_CIPHER_SUITE_WEP40:	case WLAN_CIPHER_SUITE_WEP104:		if (key_idx > 3)			return -EINVAL;	default:		break;	} 	switch (params->cipher) {	case WLAN_CIPHER_SUITE_WEP40:		if (params->key_len != WLAN_KEY_LEN_WEP40)			return -EINVAL;		break;	case WLAN_CIPHER_SUITE_TKIP:		if (params->key_len != WLAN_KEY_LEN_TKIP)			return -EINVAL;		break;	case WLAN_CIPHER_SUITE_CCMP:		if (params->key_len != WLAN_KEY_LEN_CCMP)			return -EINVAL;		break;	case WLAN_CIPHER_SUITE_CCMP_256:		if (params->key_len != WLAN_KEY_LEN_CCMP_256)			return -EINVAL;		break;	case WLAN_CIPHER_SUITE_GCMP:		if (params->key_len != WLAN_KEY_LEN_GCMP)			return -EINVAL;		break;	case WLAN_CIPHER_SUITE_GCMP_256:		if (params->key_len != WLAN_KEY_LEN_GCMP_256)			return -EINVAL;		break;	case WLAN_CIPHER_SUITE_WEP104:		if (params->key_len != WLAN_KEY_LEN_WEP104)			return -EINVAL;		break;	case WLAN_CIPHER_SUITE_AES_CMAC:		if (params->key_len != WLAN_KEY_LEN_AES_CMAC)			return -EINVAL;		break;	case WLAN_CIPHER_SUITE_BIP_CMAC_256:		if (params->key_len != WLAN_KEY_LEN_BIP_CMAC_256)			return -EINVAL;		break;	case WLAN_CIPHER_SUITE_BIP_GMAC_128:		if (params->key_len != WLAN_KEY_LEN_BIP_GMAC_128)			return -EINVAL;		break;	case WLAN_CIPHER_SUITE_BIP_GMAC_256:		if (params->key_len != WLAN_KEY_LEN_BIP_GMAC_256)			return -EINVAL;		break;	default:		/*		 * We don't know anything about this algorithm,		 * allow using it -- but the driver must check		 * all parameters! We still check below whether		 * or not the driver supports this algorithm,		 * of course.		 */		break;	} 	if (params->seq) {		switch (params->cipher) {		case WLAN_CIPHER_SUITE_WEP40:		case WLAN_CIPHER_SUITE_WEP104:			/* These ciphers do not use key sequence */			return -EINVAL;		case WLAN_CIPHER_SUITE_TKIP:		case WLAN_CIPHER_SUITE_CCMP:		case WLAN_CIPHER_SUITE_CCMP_256:		case WLAN_CIPHER_SUITE_GCMP:		case WLAN_CIPHER_SUITE_GCMP_256:		case WLAN_CIPHER_SUITE_AES_CMAC:		case WLAN_CIPHER_SUITE_BIP_CMAC_256:		case WLAN_CIPHER_SUITE_BIP_GMAC_128:		case WLAN_CIPHER_SUITE_BIP_GMAC_256:			if (params->seq_len != 6)				return -EINVAL;			break;		}	} 	if (!cfg80211_supported_cipher_suite(&rdev->wiphy, params->cipher))		return -EINVAL; 	return 0;} unsigned int __attribute_const__ ieee80211_hdrlen(__le16 fc){	unsigned int hdrlen = 24; 	if (ieee80211_is_data(fc)) {		if (ieee80211_has_a4(fc))			hdrlen = 30;		if (ieee80211_is_data_qos(fc)) {			hdrlen += IEEE80211_QOS_CTL_LEN;			if (ieee80211_has_order(fc))				hdrlen += IEEE80211_HT_CTL_LEN;		}		goto out;	} 	if (ieee80211_is_mgmt(fc)) {		if (ieee80211_has_order(fc))			hdrlen += IEEE80211_HT_CTL_LEN;		goto out;	} 	if (ieee80211_is_ctl(fc)) {		/*		 * ACK and CTS are 10 bytes, all others 16. To see how		 * to get this condition consider		 *   subtype mask:   0b0000000011110000 (0x00F0)		 *   ACK subtype:    0b0000000011010000 (0x00D0)		 *   CTS subtype:    0b0000000011000000 (0x00C0)		 *   bits that matter:         ^^^      (0x00E0)		 *   value of those: 0b0000000011000000 (0x00C0)		 */		if ((fc & cpu_to_le16(0x00E0)) == cpu_to_le16(0x00C0))			hdrlen = 10;		else			hdrlen = 16;	}out:	return hdrlen;}EXPORT_SYMBOL(ieee80211_hdrlen); unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb){	const struct ieee80211_hdr *hdr =			(const struct ieee80211_hdr *)skb->data;	unsigned int hdrlen; 	if (unlikely(skb->len < 10))		return 0;	hdrlen = ieee80211_hdrlen(hdr->frame_control);	if (unlikely(hdrlen > skb->len))		return 0;	return hdrlen;}EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb); static unsigned int __ieee80211_get_mesh_hdrlen(u8 flags){	int ae = flags & MESH_FLAGS_AE;	/* 802.11-2012, 8.2.4.7.3 */	switch (ae) {	default:	case 0:		return 6;	case MESH_FLAGS_AE_A4:		return 12;	case MESH_FLAGS_AE_A5_A6:		return 18;	}} unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr){	return __ieee80211_get_mesh_hdrlen(meshhdr->flags);}EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen); int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,				  const u8 *addr, enum nl80211_iftype iftype,				  u8 data_offset){	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;	struct {		u8 hdr[ETH_ALEN] __aligned(2);		__be16 proto;	} payload;	struct ethhdr tmp;	u16 hdrlen;	u8 mesh_flags = 0; 	if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))		return -1; 	hdrlen = ieee80211_hdrlen(hdr->frame_control) + data_offset;	if (skb->len < hdrlen + 8)		return -1; 	/* convert IEEE 802.11 header + possible LLC headers into Ethernet	 * header	 * IEEE 802.11 address fields:	 * ToDS FromDS Addr1 Addr2 Addr3 Addr4	 *   0     0   DA    SA    BSSID n/a	 *   0     1   DA    BSSID SA    n/a	 *   1     0   BSSID SA    DA    n/a	 *   1     1   RA    TA    DA    SA

Lines 1–500 of 2177.