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

ocb.c (6815B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * OCB mode implementation
      4 *
      5 * Copyright: (c) 2014 Czech Technical University in Prague
      6 *            (c) 2014 Volkswagen Group Research
      7 * Author:    Rostislav Lisovy <rostislav.lisovy@fel.cvut.cz>
      8 * Funded by: Volkswagen Group Research
      9 */
     10
     11#include <linux/delay.h>
     12#include <linux/if_ether.h>
     13#include <linux/skbuff.h>
     14#include <linux/if_arp.h>
     15#include <linux/etherdevice.h>
     16#include <linux/rtnetlink.h>
     17#include <net/mac80211.h>
     18#include <asm/unaligned.h>
     19
     20#include "ieee80211_i.h"
     21#include "driver-ops.h"
     22#include "rate.h"
     23
     24#define IEEE80211_OCB_HOUSEKEEPING_INTERVAL		(60 * HZ)
     25#define IEEE80211_OCB_PEER_INACTIVITY_LIMIT		(240 * HZ)
     26#define IEEE80211_OCB_MAX_STA_ENTRIES			128
     27
     28/**
     29 * enum ocb_deferred_task_flags - mac80211 OCB deferred tasks
     30 * @OCB_WORK_HOUSEKEEPING: run the periodic OCB housekeeping tasks
     31 *
     32 * These flags are used in @wrkq_flags field of &struct ieee80211_if_ocb
     33 */
     34enum ocb_deferred_task_flags {
     35	OCB_WORK_HOUSEKEEPING,
     36};
     37
     38void ieee80211_ocb_rx_no_sta(struct ieee80211_sub_if_data *sdata,
     39			     const u8 *bssid, const u8 *addr,
     40			     u32 supp_rates)
     41{
     42	struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
     43	struct ieee80211_local *local = sdata->local;
     44	struct ieee80211_chanctx_conf *chanctx_conf;
     45	struct ieee80211_supported_band *sband;
     46	enum nl80211_bss_scan_width scan_width;
     47	struct sta_info *sta;
     48	int band;
     49
     50	/* XXX: Consider removing the least recently used entry and
     51	 *      allow new one to be added.
     52	 */
     53	if (local->num_sta >= IEEE80211_OCB_MAX_STA_ENTRIES) {
     54		net_info_ratelimited("%s: No room for a new OCB STA entry %pM\n",
     55				     sdata->name, addr);
     56		return;
     57	}
     58
     59	ocb_dbg(sdata, "Adding new OCB station %pM\n", addr);
     60
     61	rcu_read_lock();
     62	chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
     63	if (WARN_ON_ONCE(!chanctx_conf)) {
     64		rcu_read_unlock();
     65		return;
     66	}
     67	band = chanctx_conf->def.chan->band;
     68	scan_width = cfg80211_chandef_to_scan_width(&chanctx_conf->def);
     69	rcu_read_unlock();
     70
     71	sta = sta_info_alloc(sdata, addr, GFP_ATOMIC);
     72	if (!sta)
     73		return;
     74
     75	/* Add only mandatory rates for now */
     76	sband = local->hw.wiphy->bands[band];
     77	sta->sta.deflink.supp_rates[band] =
     78		ieee80211_mandatory_rates(sband, scan_width);
     79
     80	spin_lock(&ifocb->incomplete_lock);
     81	list_add(&sta->list, &ifocb->incomplete_stations);
     82	spin_unlock(&ifocb->incomplete_lock);
     83	ieee80211_queue_work(&local->hw, &sdata->work);
     84}
     85
     86static struct sta_info *ieee80211_ocb_finish_sta(struct sta_info *sta)
     87	__acquires(RCU)
     88{
     89	struct ieee80211_sub_if_data *sdata = sta->sdata;
     90	u8 addr[ETH_ALEN];
     91
     92	memcpy(addr, sta->sta.addr, ETH_ALEN);
     93
     94	ocb_dbg(sdata, "Adding new IBSS station %pM (dev=%s)\n",
     95		addr, sdata->name);
     96
     97	sta_info_move_state(sta, IEEE80211_STA_AUTH);
     98	sta_info_move_state(sta, IEEE80211_STA_ASSOC);
     99	sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
    100
    101	rate_control_rate_init(sta);
    102
    103	/* If it fails, maybe we raced another insertion? */
    104	if (sta_info_insert_rcu(sta))
    105		return sta_info_get(sdata, addr);
    106	return sta;
    107}
    108
    109static void ieee80211_ocb_housekeeping(struct ieee80211_sub_if_data *sdata)
    110{
    111	struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
    112
    113	ocb_dbg(sdata, "Running ocb housekeeping\n");
    114
    115	ieee80211_sta_expire(sdata, IEEE80211_OCB_PEER_INACTIVITY_LIMIT);
    116
    117	mod_timer(&ifocb->housekeeping_timer,
    118		  round_jiffies(jiffies + IEEE80211_OCB_HOUSEKEEPING_INTERVAL));
    119}
    120
    121void ieee80211_ocb_work(struct ieee80211_sub_if_data *sdata)
    122{
    123	struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
    124	struct sta_info *sta;
    125
    126	if (ifocb->joined != true)
    127		return;
    128
    129	sdata_lock(sdata);
    130
    131	spin_lock_bh(&ifocb->incomplete_lock);
    132	while (!list_empty(&ifocb->incomplete_stations)) {
    133		sta = list_first_entry(&ifocb->incomplete_stations,
    134				       struct sta_info, list);
    135		list_del(&sta->list);
    136		spin_unlock_bh(&ifocb->incomplete_lock);
    137
    138		ieee80211_ocb_finish_sta(sta);
    139		rcu_read_unlock();
    140		spin_lock_bh(&ifocb->incomplete_lock);
    141	}
    142	spin_unlock_bh(&ifocb->incomplete_lock);
    143
    144	if (test_and_clear_bit(OCB_WORK_HOUSEKEEPING, &ifocb->wrkq_flags))
    145		ieee80211_ocb_housekeeping(sdata);
    146
    147	sdata_unlock(sdata);
    148}
    149
    150static void ieee80211_ocb_housekeeping_timer(struct timer_list *t)
    151{
    152	struct ieee80211_sub_if_data *sdata =
    153		from_timer(sdata, t, u.ocb.housekeeping_timer);
    154	struct ieee80211_local *local = sdata->local;
    155	struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
    156
    157	set_bit(OCB_WORK_HOUSEKEEPING, &ifocb->wrkq_flags);
    158
    159	ieee80211_queue_work(&local->hw, &sdata->work);
    160}
    161
    162void ieee80211_ocb_setup_sdata(struct ieee80211_sub_if_data *sdata)
    163{
    164	struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
    165
    166	timer_setup(&ifocb->housekeeping_timer,
    167		    ieee80211_ocb_housekeeping_timer, 0);
    168	INIT_LIST_HEAD(&ifocb->incomplete_stations);
    169	spin_lock_init(&ifocb->incomplete_lock);
    170}
    171
    172int ieee80211_ocb_join(struct ieee80211_sub_if_data *sdata,
    173		       struct ocb_setup *setup)
    174{
    175	struct ieee80211_local *local = sdata->local;
    176	struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
    177	u32 changed = BSS_CHANGED_OCB | BSS_CHANGED_BSSID;
    178	int err;
    179
    180	if (ifocb->joined == true)
    181		return -EINVAL;
    182
    183	sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
    184	sdata->smps_mode = IEEE80211_SMPS_OFF;
    185	sdata->needed_rx_chains = sdata->local->rx_chains;
    186
    187	mutex_lock(&sdata->local->mtx);
    188	err = ieee80211_vif_use_channel(sdata, &setup->chandef,
    189					IEEE80211_CHANCTX_SHARED);
    190	mutex_unlock(&sdata->local->mtx);
    191	if (err)
    192		return err;
    193
    194	ieee80211_bss_info_change_notify(sdata, changed);
    195
    196	ifocb->joined = true;
    197
    198	set_bit(OCB_WORK_HOUSEKEEPING, &ifocb->wrkq_flags);
    199	ieee80211_queue_work(&local->hw, &sdata->work);
    200
    201	netif_carrier_on(sdata->dev);
    202	return 0;
    203}
    204
    205int ieee80211_ocb_leave(struct ieee80211_sub_if_data *sdata)
    206{
    207	struct ieee80211_if_ocb *ifocb = &sdata->u.ocb;
    208	struct ieee80211_local *local = sdata->local;
    209	struct sta_info *sta;
    210
    211	ifocb->joined = false;
    212	sta_info_flush(sdata);
    213
    214	spin_lock_bh(&ifocb->incomplete_lock);
    215	while (!list_empty(&ifocb->incomplete_stations)) {
    216		sta = list_first_entry(&ifocb->incomplete_stations,
    217				       struct sta_info, list);
    218		list_del(&sta->list);
    219		spin_unlock_bh(&ifocb->incomplete_lock);
    220
    221		sta_info_free(local, sta);
    222		spin_lock_bh(&ifocb->incomplete_lock);
    223	}
    224	spin_unlock_bh(&ifocb->incomplete_lock);
    225
    226	netif_carrier_off(sdata->dev);
    227	clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
    228	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_OCB);
    229
    230	mutex_lock(&sdata->local->mtx);
    231	ieee80211_vif_release_channel(sdata);
    232	mutex_unlock(&sdata->local->mtx);
    233
    234	skb_queue_purge(&sdata->skb_queue);
    235
    236	del_timer_sync(&sdata->u.ocb.housekeeping_timer);
    237	/* If the timer fired while we waited for it, it will have
    238	 * requeued the work. Now the work will be running again
    239	 * but will not rearm the timer again because it checks
    240	 * whether we are connected to the network or not -- at this
    241	 * point we shouldn't be anymore.
    242	 */
    243
    244	return 0;
    245}