cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

dot11d.c (4933B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* Implement 802.11d. */
      3
      4#include "dot11d.h"
      5
      6void rtl8192u_dot11d_init(struct ieee80211_device *ieee)
      7{
      8	struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(ieee);
      9
     10	dot11d_info->dot11d_enabled = false;
     11
     12	dot11d_info->state = DOT11D_STATE_NONE;
     13	dot11d_info->country_ie_len = 0;
     14	memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1);
     15	memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER + 1);
     16	RESET_CIE_WATCHDOG(ieee);
     17}
     18EXPORT_SYMBOL(rtl8192u_dot11d_init);
     19
     20/* Reset to the state as we are just entering a regulatory domain. */
     21void dot11d_reset(struct ieee80211_device *ieee)
     22{
     23	u32 i;
     24	struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(ieee);
     25	/* Clear old channel map */
     26	memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1);
     27	memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER + 1);
     28	/* Set new channel map */
     29	for (i = 1; i <= 11; i++)
     30		(dot11d_info->channel_map)[i] = 1;
     31
     32	for (i = 12; i <= 14; i++)
     33		(dot11d_info->channel_map)[i] = 2;
     34
     35	dot11d_info->state = DOT11D_STATE_NONE;
     36	dot11d_info->country_ie_len = 0;
     37	RESET_CIE_WATCHDOG(ieee);
     38}
     39EXPORT_SYMBOL(dot11d_reset);
     40
     41/*
     42 * Update country IE from Beacon or Probe Resopnse and configure PHY for
     43 * operation in the regulatory domain.
     44 *
     45 * TODO: Configure Tx power.
     46 * Assumption:
     47 * 1. IS_DOT11D_ENABLE() is TRUE.
     48 * 2. Input IE is an valid one.
     49 */
     50void dot11d_update_country_ie(struct ieee80211_device *dev, u8 *pTaddr,
     51			    u16 CoutryIeLen, u8 *pCoutryIe)
     52{
     53	struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(dev);
     54	u8 i, j, NumTriples, MaxChnlNum;
     55	struct chnl_txpower_triple *pTriple;
     56
     57	memset(dot11d_info->channel_map, 0, MAX_CHANNEL_NUMBER + 1);
     58	memset(dot11d_info->max_tx_pwr_dbm_list, 0xFF, MAX_CHANNEL_NUMBER + 1);
     59	MaxChnlNum = 0;
     60	NumTriples = (CoutryIeLen - 3) / 3; /* skip 3-byte country string. */
     61	pTriple = (struct chnl_txpower_triple *)(pCoutryIe + 3);
     62	for (i = 0; i < NumTriples; i++) {
     63		if (MaxChnlNum >= pTriple->first_channel) {
     64			/* It is not in a monotonically increasing order, so
     65			 * stop processing.
     66			 */
     67			netdev_err(dev->dev, "%s: Invalid country IE, skip it 1\n", __func__);
     68			return;
     69		}
     70		if (MAX_CHANNEL_NUMBER < (pTriple->first_channel + pTriple->num_channels)) {
     71			/* It is not a valid set of channel id, so stop
     72			 * processing.
     73			 */
     74			netdev_err(dev->dev, "%s: Invalid country IE, skip it 2\n", __func__);
     75			return;
     76		}
     77
     78		for (j = 0; j < pTriple->num_channels; j++) {
     79			dot11d_info->channel_map[pTriple->first_channel + j] = 1;
     80			dot11d_info->max_tx_pwr_dbm_list[pTriple->first_channel + j] = pTriple->max_tx_pwr_dbm;
     81			MaxChnlNum = pTriple->first_channel + j;
     82		}
     83
     84		pTriple = (struct chnl_txpower_triple *)((u8 *)pTriple + 3);
     85	}
     86	netdev_info(dev->dev, "Channel List:");
     87	for (i = 1; i <= MAX_CHANNEL_NUMBER; i++)
     88		if (dot11d_info->channel_map[i] > 0)
     89			netdev_info(dev->dev, " %d", i);
     90	netdev_info(dev->dev, "\n");
     91
     92	UPDATE_CIE_SRC(dev, pTaddr);
     93
     94	dot11d_info->country_ie_len = CoutryIeLen;
     95	memcpy(dot11d_info->country_ie_buf, pCoutryIe, CoutryIeLen);
     96	dot11d_info->state = DOT11D_STATE_LEARNED;
     97}
     98EXPORT_SYMBOL(dot11d_update_country_ie);
     99
    100u8 dot11d_get_max_tx_pwr_in_dbm(struct ieee80211_device *dev, u8 Channel)
    101{
    102	struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(dev);
    103	u8 MaxTxPwrInDbm = 255;
    104
    105	if (Channel > MAX_CHANNEL_NUMBER) {
    106		netdev_err(dev->dev, "%s: Invalid Channel\n", __func__);
    107		return MaxTxPwrInDbm;
    108	}
    109	if (dot11d_info->channel_map[Channel])
    110		MaxTxPwrInDbm = dot11d_info->max_tx_pwr_dbm_list[Channel];
    111
    112	return MaxTxPwrInDbm;
    113}
    114EXPORT_SYMBOL(dot11d_get_max_tx_pwr_in_dbm);
    115
    116void dot11d_scan_complete(struct ieee80211_device *dev)
    117{
    118	struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(dev);
    119
    120	switch (dot11d_info->state) {
    121	case DOT11D_STATE_LEARNED:
    122		dot11d_info->state = DOT11D_STATE_DONE;
    123		break;
    124
    125	case DOT11D_STATE_DONE:
    126		if (GET_CIE_WATCHDOG(dev) == 0) {
    127			/* Reset country IE if previous one is gone. */
    128			dot11d_reset(dev);
    129		}
    130		break;
    131	case DOT11D_STATE_NONE:
    132		break;
    133	}
    134}
    135EXPORT_SYMBOL(dot11d_scan_complete);
    136
    137int is_legal_channel(struct ieee80211_device *dev, u8 channel)
    138{
    139	struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(dev);
    140
    141	if (channel > MAX_CHANNEL_NUMBER) {
    142		netdev_err(dev->dev, "%s: Invalid Channel\n", __func__);
    143		return 0;
    144	}
    145	if (dot11d_info->channel_map[channel] > 0)
    146		return 1;
    147	return 0;
    148}
    149EXPORT_SYMBOL(is_legal_channel);
    150
    151int to_legal_channel(struct ieee80211_device *dev, u8 channel)
    152{
    153	struct rt_dot11d_info *dot11d_info = GET_DOT11D_INFO(dev);
    154	u8 default_chn = 0;
    155	u32 i = 0;
    156
    157	for (i = 1; i <= MAX_CHANNEL_NUMBER; i++) {
    158		if (dot11d_info->channel_map[i] > 0) {
    159			default_chn = i;
    160			break;
    161		}
    162	}
    163
    164	if (channel > MAX_CHANNEL_NUMBER) {
    165		netdev_err(dev->dev, "%s: Invalid Channel\n", __func__);
    166		return default_chn;
    167	}
    168
    169	if (dot11d_info->channel_map[channel] > 0)
    170		return channel;
    171
    172	return default_chn;
    173}
    174EXPORT_SYMBOL(to_legal_channel);