mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-31 05:54:26 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			162 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			162 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| Subject: mac80211: support getting key sequence counters via cfg80211
 | |
| 
 | |
| This implements cfg80211's get_key() to allow retrieving the sequence
 | |
| counter for a TKIP or CCMP key from userspace. It also cleans up and
 | |
| documents the associated low-level driver interface.
 | |
| 
 | |
| Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
 | |
| 
 | |
| ---
 | |
|  include/net/mac80211.h |   14 ++------
 | |
|  net/mac80211/cfg.c     |   85 ++++++++++++++++++++++++++++++++++++++++++++++++-
 | |
|  2 files changed, 89 insertions(+), 10 deletions(-)
 | |
| 
 | |
| Index: mac80211/net/mac80211/cfg.c
 | |
| ===================================================================
 | |
| --- mac80211.orig/net/mac80211/cfg.c	2007-11-11 15:46:41.497954646 +0100
 | |
| +++ mac80211/net/mac80211/cfg.c	2007-11-11 15:46:51.346515884 +0100
 | |
| @@ -1,7 +1,7 @@
 | |
|  /*
 | |
|   * mac80211 configuration hooks for cfg80211
 | |
|   *
 | |
| - * Copyright 2006	Johannes Berg <johannes@sipsolutions.net>
 | |
| + * Copyright 2006, 2007	Johannes Berg <johannes@sipsolutions.net>
 | |
|   *
 | |
|   * This file is GPLv2 as found in COPYING.
 | |
|   */
 | |
| @@ -180,6 +180,88 @@
 | |
|  	return 0;
 | |
|  }
 | |
|  
 | |
| +static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 | |
| +			     u8 key_idx, u8 *mac_addr, void *cookie,
 | |
| +			     void (*callback)(void *cookie,
 | |
| +					      struct key_params *params))
 | |
| +{
 | |
| +	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 | |
| +	struct sta_info *sta = NULL;
 | |
| +	u8 seq[6] = {0};
 | |
| +	struct key_params params;
 | |
| +	struct ieee80211_key *key;
 | |
| +	u32 iv32;
 | |
| +	u16 iv16;
 | |
| +	int err = -ENOENT;
 | |
| +
 | |
| +	if (mac_addr) {
 | |
| +		sta = sta_info_get(sdata->local, mac_addr);
 | |
| +		if (!sta)
 | |
| +			goto out;
 | |
| +
 | |
| +		key = sta->key;
 | |
| +	} else
 | |
| +		key = sdata->keys[key_idx];
 | |
| +
 | |
| +	if (!key)
 | |
| +		goto out;
 | |
| +
 | |
| +	memset(¶ms, 0, sizeof(params));
 | |
| +
 | |
| +	switch (key->conf.alg) {
 | |
| +	case ALG_TKIP:
 | |
| +		params.cipher = WLAN_CIPHER_SUITE_TKIP;
 | |
| +
 | |
| +		iv32 = key->u.tkip.iv32;
 | |
| +		iv16 = key->u.tkip.iv16;
 | |
| +
 | |
| +		if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
 | |
| +		    sdata->local->ops->get_tkip_seq)
 | |
| +			sdata->local->ops->get_tkip_seq(
 | |
| +				local_to_hw(sdata->local),
 | |
| +				key->conf.hw_key_idx,
 | |
| +				&iv32, &iv16);
 | |
| +
 | |
| +		seq[0] = iv16 & 0xff;
 | |
| +		seq[1] = (iv16 >> 8) & 0xff;
 | |
| +		seq[2] = iv32 & 0xff;
 | |
| +		seq[3] = (iv32 >> 8) & 0xff;
 | |
| +		seq[4] = (iv32 >> 16) & 0xff;
 | |
| +		seq[5] = (iv32 >> 24) & 0xff;
 | |
| +		params.seq = seq;
 | |
| +		params.seq_len = 6;
 | |
| +		break;
 | |
| +	case ALG_CCMP:
 | |
| +		params.cipher = WLAN_CIPHER_SUITE_CCMP;
 | |
| +		seq[0] = key->u.ccmp.tx_pn[5];
 | |
| +		seq[1] = key->u.ccmp.tx_pn[4];
 | |
| +		seq[2] = key->u.ccmp.tx_pn[3];
 | |
| +		seq[3] = key->u.ccmp.tx_pn[2];
 | |
| +		seq[4] = key->u.ccmp.tx_pn[1];
 | |
| +		seq[5] = key->u.ccmp.tx_pn[0];
 | |
| +		params.seq = seq;
 | |
| +		params.seq_len = 6;
 | |
| +		break;
 | |
| +	case ALG_WEP:
 | |
| +		if (key->conf.keylen == 5)
 | |
| +			params.cipher = WLAN_CIPHER_SUITE_WEP40;
 | |
| +		else
 | |
| +			params.cipher = WLAN_CIPHER_SUITE_WEP104;
 | |
| +		break;
 | |
| +	}
 | |
| +
 | |
| +	params.key = key->conf.key;
 | |
| +	params.key_len = key->conf.keylen;
 | |
| +
 | |
| +	callback(cookie, ¶ms);
 | |
| +	err = 0;
 | |
| +
 | |
| + out:
 | |
| +	if (sta)
 | |
| +		sta_info_put(sta);
 | |
| +	return err;
 | |
| +}
 | |
| +
 | |
|  static int ieee80211_config_default_key(struct wiphy *wiphy,
 | |
|  					struct net_device *dev,
 | |
|  					u8 key_idx)
 | |
| @@ -198,5 +280,6 @@
 | |
|  	.change_virtual_intf = ieee80211_change_iface,
 | |
|  	.add_key = ieee80211_add_key,
 | |
|  	.del_key = ieee80211_del_key,
 | |
| +	.get_key = ieee80211_get_key,
 | |
|  	.set_default_key = ieee80211_config_default_key,
 | |
|  };
 | |
| Index: mac80211/include/net/mac80211.h
 | |
| ===================================================================
 | |
| --- mac80211.orig/include/net/mac80211.h	2007-11-11 15:46:41.377947807 +0100
 | |
| +++ mac80211/include/net/mac80211.h	2007-11-11 15:47:08.183475366 +0100
 | |
| @@ -598,9 +598,6 @@
 | |
|  	u8 key[0];
 | |
|  };
 | |
|  
 | |
| -#define IEEE80211_SEQ_COUNTER_RX	0
 | |
| -#define IEEE80211_SEQ_COUNTER_TX	1
 | |
| -
 | |
|  /**
 | |
|   * enum set_key_cmd - key command
 | |
|   *
 | |
| @@ -947,9 +944,9 @@
 | |
|   *
 | |
|   * @get_stats: return low-level statistics
 | |
|   *
 | |
| - * @get_sequence_counter: For devices that have internal sequence counters this
 | |
| - *	callback allows mac80211 to access the current value of a counter.
 | |
| - *	This callback seems not well-defined, tell us if you need it.
 | |
| + * @get_tkip_seq: If your device implements TKIP encryption in hardware this
 | |
| + *	callback should be provided to read the TKIP transmit IVs (both IV32
 | |
| + *	and IV16) for the given key from hardware.
 | |
|   *
 | |
|   * @set_rts_threshold: Configuration of RTS threshold (if device needs it)
 | |
|   *
 | |
| @@ -1022,9 +1019,8 @@
 | |
|  	int (*hw_scan)(struct ieee80211_hw *hw, u8 *ssid, size_t len);
 | |
|  	int (*get_stats)(struct ieee80211_hw *hw,
 | |
|  			 struct ieee80211_low_level_stats *stats);
 | |
| -	int (*get_sequence_counter)(struct ieee80211_hw *hw,
 | |
| -				    u8* addr, u8 keyidx, u8 txrx,
 | |
| -				    u32* iv32, u16* iv16);
 | |
| +	void (*get_tkip_seq)(struct ieee80211_hw *hw, u8 hw_key_idx,
 | |
| +			     u32 *iv32, u16 *iv16);
 | |
|  	int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value);
 | |
|  	int (*set_frag_threshold)(struct ieee80211_hw *hw, u32 value);
 | |
|  	int (*set_retry_limit)(struct ieee80211_hw *hw,
 |