aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h14
-rw-r--r--net/mac80211/cfg.c85
2 files changed, 89 insertions, 10 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 5b9e7a262448..a762a75ae62d 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -647,9 +647,6 @@ struct ieee80211_key_conf {
647 u8 key[0]; 647 u8 key[0];
648}; 648};
649 649
650#define IEEE80211_SEQ_COUNTER_RX 0
651#define IEEE80211_SEQ_COUNTER_TX 1
652
653/** 650/**
654 * enum set_key_cmd - key command 651 * enum set_key_cmd - key command
655 * 652 *
@@ -996,9 +993,9 @@ enum ieee80211_erp_change_flags {
996 * 993 *
997 * @get_stats: return low-level statistics 994 * @get_stats: return low-level statistics
998 * 995 *
999 * @get_sequence_counter: For devices that have internal sequence counters this 996 * @get_tkip_seq: If your device implements TKIP encryption in hardware this
1000 * callback allows mac80211 to access the current value of a counter. 997 * callback should be provided to read the TKIP transmit IVs (both IV32
1001 * This callback seems not well-defined, tell us if you need it. 998 * and IV16) for the given key from hardware.
1002 * 999 *
1003 * @set_rts_threshold: Configuration of RTS threshold (if device needs it) 1000 * @set_rts_threshold: Configuration of RTS threshold (if device needs it)
1004 * 1001 *
@@ -1073,9 +1070,8 @@ struct ieee80211_ops {
1073 int (*hw_scan)(struct ieee80211_hw *hw, u8 *ssid, size_t len); 1070 int (*hw_scan)(struct ieee80211_hw *hw, u8 *ssid, size_t len);
1074 int (*get_stats)(struct ieee80211_hw *hw, 1071 int (*get_stats)(struct ieee80211_hw *hw,
1075 struct ieee80211_low_level_stats *stats); 1072 struct ieee80211_low_level_stats *stats);
1076 int (*get_sequence_counter)(struct ieee80211_hw *hw, 1073 void (*get_tkip_seq)(struct ieee80211_hw *hw, u8 hw_key_idx,
1077 u8* addr, u8 keyidx, u8 txrx, 1074 u32 *iv32, u16 *iv16);
1078 u32* iv32, u16* iv16);
1079 int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value); 1075 int (*set_rts_threshold)(struct ieee80211_hw *hw, u32 value);
1080 int (*set_frag_threshold)(struct ieee80211_hw *hw, u32 value); 1076 int (*set_frag_threshold)(struct ieee80211_hw *hw, u32 value);
1081 int (*set_retry_limit)(struct ieee80211_hw *hw, 1077 int (*set_retry_limit)(struct ieee80211_hw *hw,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index d49f7b58b05c..4c1ce353c662 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * mac80211 configuration hooks for cfg80211 2 * mac80211 configuration hooks for cfg80211
3 * 3 *
4 * Copyright 2006 Johannes Berg <johannes@sipsolutions.net> 4 * Copyright 2006, 2007 Johannes Berg <johannes@sipsolutions.net>
5 * 5 *
6 * This file is GPLv2 as found in COPYING. 6 * This file is GPLv2 as found in COPYING.
7 */ 7 */
@@ -175,6 +175,88 @@ static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
175 return 0; 175 return 0;
176} 176}
177 177
178static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
179 u8 key_idx, u8 *mac_addr, void *cookie,
180 void (*callback)(void *cookie,
181 struct key_params *params))
182{
183 struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
184 struct sta_info *sta = NULL;
185 u8 seq[6] = {0};
186 struct key_params params;
187 struct ieee80211_key *key;
188 u32 iv32;
189 u16 iv16;
190 int err = -ENOENT;
191
192 if (mac_addr) {
193 sta = sta_info_get(sdata->local, mac_addr);
194 if (!sta)
195 goto out;
196
197 key = sta->key;
198 } else
199 key = sdata->keys[key_idx];
200
201 if (!key)
202 goto out;
203
204 memset(&params, 0, sizeof(params));
205
206 switch (key->conf.alg) {
207 case ALG_TKIP:
208 params.cipher = WLAN_CIPHER_SUITE_TKIP;
209
210 iv32 = key->u.tkip.iv32;
211 iv16 = key->u.tkip.iv16;
212
213 if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
214 sdata->local->ops->get_tkip_seq)
215 sdata->local->ops->get_tkip_seq(
216 local_to_hw(sdata->local),
217 key->conf.hw_key_idx,
218 &iv32, &iv16);
219
220 seq[0] = iv16 & 0xff;
221 seq[1] = (iv16 >> 8) & 0xff;
222 seq[2] = iv32 & 0xff;
223 seq[3] = (iv32 >> 8) & 0xff;
224 seq[4] = (iv32 >> 16) & 0xff;
225 seq[5] = (iv32 >> 24) & 0xff;
226 params.seq = seq;
227 params.seq_len = 6;
228 break;
229 case ALG_CCMP:
230 params.cipher = WLAN_CIPHER_SUITE_CCMP;
231 seq[0] = key->u.ccmp.tx_pn[5];
232 seq[1] = key->u.ccmp.tx_pn[4];
233 seq[2] = key->u.ccmp.tx_pn[3];
234 seq[3] = key->u.ccmp.tx_pn[2];
235 seq[4] = key->u.ccmp.tx_pn[1];
236 seq[5] = key->u.ccmp.tx_pn[0];
237 params.seq = seq;
238 params.seq_len = 6;
239 break;
240 case ALG_WEP:
241 if (key->conf.keylen == 5)
242 params.cipher = WLAN_CIPHER_SUITE_WEP40;
243 else
244 params.cipher = WLAN_CIPHER_SUITE_WEP104;
245 break;
246 }
247
248 params.key = key->conf.key;
249 params.key_len = key->conf.keylen;
250
251 callback(cookie, &params);
252 err = 0;
253
254 out:
255 if (sta)
256 sta_info_put(sta);
257 return err;
258}
259
178static int ieee80211_config_default_key(struct wiphy *wiphy, 260static int ieee80211_config_default_key(struct wiphy *wiphy,
179 struct net_device *dev, 261 struct net_device *dev,
180 u8 key_idx) 262 u8 key_idx)
@@ -193,5 +275,6 @@ struct cfg80211_ops mac80211_config_ops = {
193 .change_virtual_intf = ieee80211_change_iface, 275 .change_virtual_intf = ieee80211_change_iface,
194 .add_key = ieee80211_add_key, 276 .add_key = ieee80211_add_key,
195 .del_key = ieee80211_del_key, 277 .del_key = ieee80211_del_key,
278 .get_key = ieee80211_get_key,
196 .set_default_key = ieee80211_config_default_key, 279 .set_default_key = ieee80211_config_default_key,
197}; 280};