diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/ieee80211.c | 7 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 2 | ||||
-rw-r--r-- | net/mac80211/ieee80211_ioctl.c | 31 | ||||
-rw-r--r-- | net/mac80211/ieee80211_sta.c | 125 | ||||
-rw-r--r-- | net/mac80211/tkip.c | 68 | ||||
-rw-r--r-- | net/mac80211/tkip.h | 2 | ||||
-rw-r--r-- | net/mac80211/wpa.c | 2 | ||||
-rw-r--r-- | net/wireless/util.c | 23 |
8 files changed, 186 insertions, 74 deletions
diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index 55b63712e48c..616ce10d2a38 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c | |||
@@ -386,7 +386,6 @@ static int ieee80211_stop(struct net_device *dev) | |||
386 | struct ieee80211_local *local = sdata->local; | 386 | struct ieee80211_local *local = sdata->local; |
387 | struct ieee80211_if_init_conf conf; | 387 | struct ieee80211_if_init_conf conf; |
388 | struct sta_info *sta; | 388 | struct sta_info *sta; |
389 | int i; | ||
390 | 389 | ||
391 | /* | 390 | /* |
392 | * Stop TX on this interface first. | 391 | * Stop TX on this interface first. |
@@ -400,11 +399,7 @@ static int ieee80211_stop(struct net_device *dev) | |||
400 | 399 | ||
401 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | 400 | list_for_each_entry_rcu(sta, &local->sta_list, list) { |
402 | if (sta->sdata == sdata) | 401 | if (sta->sdata == sdata) |
403 | for (i = 0; i < STA_TID_NUM; i++) | 402 | ieee80211_sta_tear_down_BA_sessions(dev, sta->addr); |
404 | ieee80211_sta_stop_rx_ba_session(sdata->dev, | ||
405 | sta->addr, i, | ||
406 | WLAN_BACK_RECIPIENT, | ||
407 | WLAN_REASON_QSTA_LEAVE_QBSS); | ||
408 | } | 403 | } |
409 | 404 | ||
410 | rcu_read_unlock(); | 405 | rcu_read_unlock(); |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 7f10ff5d4a0b..a6485f01b3c8 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -928,10 +928,12 @@ void ieee80211_send_addba_request(struct net_device *dev, const u8 *da, | |||
928 | u16 agg_size, u16 timeout); | 928 | u16 agg_size, u16 timeout); |
929 | void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, | 929 | void ieee80211_send_delba(struct net_device *dev, const u8 *da, u16 tid, |
930 | u16 initiator, u16 reason_code); | 930 | u16 initiator, u16 reason_code); |
931 | |||
931 | void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *da, | 932 | void ieee80211_sta_stop_rx_ba_session(struct net_device *dev, u8 *da, |
932 | u16 tid, u16 initiator, u16 reason); | 933 | u16 tid, u16 initiator, u16 reason); |
933 | void sta_rx_agg_session_timer_expired(unsigned long data); | 934 | void sta_rx_agg_session_timer_expired(unsigned long data); |
934 | void sta_addba_resp_timer_expired(unsigned long data); | 935 | void sta_addba_resp_timer_expired(unsigned long data); |
936 | void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr); | ||
935 | u64 ieee80211_sta_get_rates(struct ieee80211_local *local, | 937 | u64 ieee80211_sta_get_rates(struct ieee80211_local *local, |
936 | struct ieee802_11_elems *elems, | 938 | struct ieee802_11_elems *elems, |
937 | enum ieee80211_band band); | 939 | enum ieee80211_band band); |
diff --git a/net/mac80211/ieee80211_ioctl.c b/net/mac80211/ieee80211_ioctl.c index 1d91575a0fe9..5af23d318726 100644 --- a/net/mac80211/ieee80211_ioctl.c +++ b/net/mac80211/ieee80211_ioctl.c | |||
@@ -279,36 +279,15 @@ static int ieee80211_ioctl_giwmode(struct net_device *dev, | |||
279 | 279 | ||
280 | int ieee80211_set_freq(struct ieee80211_local *local, int freqMHz) | 280 | int ieee80211_set_freq(struct ieee80211_local *local, int freqMHz) |
281 | { | 281 | { |
282 | int set = 0; | ||
283 | int ret = -EINVAL; | 282 | int ret = -EINVAL; |
284 | enum ieee80211_band band; | 283 | struct ieee80211_channel *chan; |
285 | struct ieee80211_supported_band *sband; | ||
286 | int i; | ||
287 | |||
288 | for (band = 0; band < IEEE80211_NUM_BANDS; band ++) { | ||
289 | sband = local->hw.wiphy->bands[band]; | ||
290 | 284 | ||
291 | if (!sband) | 285 | chan = ieee80211_get_channel(local->hw.wiphy, freqMHz); |
292 | continue; | ||
293 | 286 | ||
294 | for (i = 0; i < sband->n_channels; i++) { | 287 | if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { |
295 | struct ieee80211_channel *chan = &sband->channels[i]; | 288 | local->oper_channel = chan; |
296 | |||
297 | if (chan->flags & IEEE80211_CHAN_DISABLED) | ||
298 | continue; | ||
299 | |||
300 | if (chan->center_freq == freqMHz) { | ||
301 | set = 1; | ||
302 | local->oper_channel = chan; | ||
303 | break; | ||
304 | } | ||
305 | } | ||
306 | if (set) | ||
307 | break; | ||
308 | } | ||
309 | 289 | ||
310 | if (set) { | 290 | if (local->sta_sw_scanning || local->sta_hw_scanning) |
311 | if (local->sta_sw_scanning) | ||
312 | ret = 0; | 291 | ret = 0; |
313 | else | 292 | else |
314 | ret = ieee80211_hw_config(local); | 293 | ret = ieee80211_hw_config(local); |
diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index 8b991ebcbb4e..cf51ca6804dd 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c | |||
@@ -220,6 +220,61 @@ static int ecw2cw(int ecw) | |||
220 | return (1 << ecw) - 1; | 220 | return (1 << ecw) - 1; |
221 | } | 221 | } |
222 | 222 | ||
223 | |||
224 | static void ieee80211_sta_def_wmm_params(struct net_device *dev, | ||
225 | struct ieee80211_sta_bss *bss, | ||
226 | int ibss) | ||
227 | { | ||
228 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
229 | struct ieee80211_local *local = sdata->local; | ||
230 | int i, have_higher_than_11mbit = 0; | ||
231 | |||
232 | |||
233 | /* cf. IEEE 802.11 9.2.12 */ | ||
234 | for (i = 0; i < bss->supp_rates_len; i++) | ||
235 | if ((bss->supp_rates[i] & 0x7f) * 5 > 110) | ||
236 | have_higher_than_11mbit = 1; | ||
237 | |||
238 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | ||
239 | have_higher_than_11mbit) | ||
240 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; | ||
241 | else | ||
242 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; | ||
243 | |||
244 | |||
245 | if (local->ops->conf_tx) { | ||
246 | struct ieee80211_tx_queue_params qparam; | ||
247 | int i; | ||
248 | |||
249 | memset(&qparam, 0, sizeof(qparam)); | ||
250 | |||
251 | qparam.aifs = 2; | ||
252 | |||
253 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | ||
254 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)) | ||
255 | qparam.cw_min = 31; | ||
256 | else | ||
257 | qparam.cw_min = 15; | ||
258 | |||
259 | qparam.cw_max = 1023; | ||
260 | qparam.txop = 0; | ||
261 | |||
262 | for (i = IEEE80211_TX_QUEUE_DATA0; i < NUM_TX_DATA_QUEUES; i++) | ||
263 | local->ops->conf_tx(local_to_hw(local), | ||
264 | i + IEEE80211_TX_QUEUE_DATA0, | ||
265 | &qparam); | ||
266 | |||
267 | if (ibss) { | ||
268 | /* IBSS uses different parameters for Beacon sending */ | ||
269 | qparam.cw_min++; | ||
270 | qparam.cw_min *= 2; | ||
271 | qparam.cw_min--; | ||
272 | local->ops->conf_tx(local_to_hw(local), | ||
273 | IEEE80211_TX_QUEUE_BEACON, &qparam); | ||
274 | } | ||
275 | } | ||
276 | } | ||
277 | |||
223 | static void ieee80211_sta_wmm_params(struct net_device *dev, | 278 | static void ieee80211_sta_wmm_params(struct net_device *dev, |
224 | struct ieee80211_if_sta *ifsta, | 279 | struct ieee80211_if_sta *ifsta, |
225 | u8 *wmm_param, size_t wmm_param_len) | 280 | u8 *wmm_param, size_t wmm_param_len) |
@@ -467,8 +522,8 @@ static void ieee80211_set_associated(struct net_device *dev, | |||
467 | memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN); | 522 | memcpy(wrqu.ap_addr.sa_data, sdata->u.sta.bssid, ETH_ALEN); |
468 | ieee80211_sta_send_associnfo(dev, ifsta); | 523 | ieee80211_sta_send_associnfo(dev, ifsta); |
469 | } else { | 524 | } else { |
525 | ieee80211_sta_tear_down_BA_sessions(dev, ifsta->bssid); | ||
470 | ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; | 526 | ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; |
471 | |||
472 | netif_carrier_off(dev); | 527 | netif_carrier_off(dev); |
473 | ieee80211_reset_erp_info(dev); | 528 | ieee80211_reset_erp_info(dev); |
474 | memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); | 529 | memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); |
@@ -1145,7 +1200,7 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev, | |||
1145 | status = WLAN_STATUS_INVALID_QOS_PARAM; | 1200 | status = WLAN_STATUS_INVALID_QOS_PARAM; |
1146 | #ifdef CONFIG_MAC80211_HT_DEBUG | 1201 | #ifdef CONFIG_MAC80211_HT_DEBUG |
1147 | if (net_ratelimit()) | 1202 | if (net_ratelimit()) |
1148 | printk(KERN_DEBUG "Block Ack Req with bad params from " | 1203 | printk(KERN_DEBUG "AddBA Req with bad params from " |
1149 | "%s on tid %u. policy %d, buffer size %d\n", | 1204 | "%s on tid %u. policy %d, buffer size %d\n", |
1150 | print_mac(mac, mgmt->sa), tid, ba_policy, | 1205 | print_mac(mac, mgmt->sa), tid, ba_policy, |
1151 | buf_size); | 1206 | buf_size); |
@@ -1169,7 +1224,7 @@ static void ieee80211_sta_process_addba_request(struct net_device *dev, | |||
1169 | if (tid_agg_rx->state != HT_AGG_STATE_IDLE) { | 1224 | if (tid_agg_rx->state != HT_AGG_STATE_IDLE) { |
1170 | #ifdef CONFIG_MAC80211_HT_DEBUG | 1225 | #ifdef CONFIG_MAC80211_HT_DEBUG |
1171 | if (net_ratelimit()) | 1226 | if (net_ratelimit()) |
1172 | printk(KERN_DEBUG "unexpected Block Ack Req from " | 1227 | printk(KERN_DEBUG "unexpected AddBA Req from " |
1173 | "%s on tid %u\n", | 1228 | "%s on tid %u\n", |
1174 | print_mac(mac, mgmt->sa), tid); | 1229 | print_mac(mac, mgmt->sa), tid); |
1175 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 1230 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
@@ -1427,7 +1482,7 @@ static void ieee80211_sta_process_delba(struct net_device *dev, | |||
1427 | if (net_ratelimit()) | 1482 | if (net_ratelimit()) |
1428 | printk(KERN_DEBUG "delba from %s (%s) tid %d reason code %d\n", | 1483 | printk(KERN_DEBUG "delba from %s (%s) tid %d reason code %d\n", |
1429 | print_mac(mac, mgmt->sa), | 1484 | print_mac(mac, mgmt->sa), |
1430 | initiator ? "recipient" : "initiator", tid, | 1485 | initiator ? "initiator" : "recipient", tid, |
1431 | mgmt->u.action.u.delba.reason_code); | 1486 | mgmt->u.action.u.delba.reason_code); |
1432 | #endif /* CONFIG_MAC80211_HT_DEBUG */ | 1487 | #endif /* CONFIG_MAC80211_HT_DEBUG */ |
1433 | 1488 | ||
@@ -1497,8 +1552,8 @@ timer_expired_exit: | |||
1497 | } | 1552 | } |
1498 | 1553 | ||
1499 | /* | 1554 | /* |
1500 | * After receiving Block Ack Request (BAR) we activated a | 1555 | * After accepting the AddBA Request we activated a timer, |
1501 | * timer after each frame arrives from the originator. | 1556 | * resetting it after each frame that arrives from the originator. |
1502 | * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed. | 1557 | * if this timer expires ieee80211_sta_stop_rx_ba_session will be executed. |
1503 | */ | 1558 | */ |
1504 | void sta_rx_agg_session_timer_expired(unsigned long data) | 1559 | void sta_rx_agg_session_timer_expired(unsigned long data) |
@@ -1518,6 +1573,19 @@ void sta_rx_agg_session_timer_expired(unsigned long data) | |||
1518 | WLAN_REASON_QSTA_TIMEOUT); | 1573 | WLAN_REASON_QSTA_TIMEOUT); |
1519 | } | 1574 | } |
1520 | 1575 | ||
1576 | void ieee80211_sta_tear_down_BA_sessions(struct net_device *dev, u8 *addr) | ||
1577 | { | ||
1578 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
1579 | int i; | ||
1580 | |||
1581 | for (i = 0; i < STA_TID_NUM; i++) { | ||
1582 | ieee80211_stop_tx_ba_session(&local->hw, addr, i, | ||
1583 | WLAN_BACK_INITIATOR); | ||
1584 | ieee80211_sta_stop_rx_ba_session(dev, addr, i, | ||
1585 | WLAN_BACK_RECIPIENT, | ||
1586 | WLAN_REASON_QSTA_LEAVE_QBSS); | ||
1587 | } | ||
1588 | } | ||
1521 | 1589 | ||
1522 | static void ieee80211_rx_mgmt_auth(struct net_device *dev, | 1590 | static void ieee80211_rx_mgmt_auth(struct net_device *dev, |
1523 | struct ieee80211_if_sta *ifsta, | 1591 | struct ieee80211_if_sta *ifsta, |
@@ -2289,6 +2357,8 @@ static int ieee80211_sta_join_ibss(struct net_device *dev, | |||
2289 | rates |= BIT(j); | 2357 | rates |= BIT(j); |
2290 | } | 2358 | } |
2291 | ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates; | 2359 | ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates; |
2360 | |||
2361 | ieee80211_sta_def_wmm_params(dev, bss, 1); | ||
2292 | } while (0); | 2362 | } while (0); |
2293 | 2363 | ||
2294 | if (skb) { | 2364 | if (skb) { |
@@ -2356,6 +2426,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2356 | struct sta_info *sta; | 2426 | struct sta_info *sta; |
2357 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2427 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2358 | u64 beacon_timestamp, rx_timestamp; | 2428 | u64 beacon_timestamp, rx_timestamp; |
2429 | struct ieee80211_channel *channel; | ||
2359 | DECLARE_MAC_BUF(mac); | 2430 | DECLARE_MAC_BUF(mac); |
2360 | DECLARE_MAC_BUF(mac2); | 2431 | DECLARE_MAC_BUF(mac2); |
2361 | 2432 | ||
@@ -2420,6 +2491,11 @@ static void ieee80211_rx_bss_info(struct net_device *dev, | |||
2420 | else | 2491 | else |
2421 | freq = rx_status->freq; | 2492 | freq = rx_status->freq; |
2422 | 2493 | ||
2494 | channel = ieee80211_get_channel(local->hw.wiphy, freq); | ||
2495 | |||
2496 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | ||
2497 | return; | ||
2498 | |||
2423 | #ifdef CONFIG_MAC80211_MESH | 2499 | #ifdef CONFIG_MAC80211_MESH |
2424 | if (elems.mesh_config) | 2500 | if (elems.mesh_config) |
2425 | bss = ieee80211_rx_mesh_bss_get(dev, elems.mesh_id, | 2501 | bss = ieee80211_rx_mesh_bss_get(dev, elems.mesh_id, |
@@ -3274,6 +3350,7 @@ static int ieee80211_sta_config_auth(struct net_device *dev, | |||
3274 | ieee80211_sta_set_ssid(dev, selected->ssid, | 3350 | ieee80211_sta_set_ssid(dev, selected->ssid, |
3275 | selected->ssid_len); | 3351 | selected->ssid_len); |
3276 | ieee80211_sta_set_bssid(dev, selected->bssid); | 3352 | ieee80211_sta_set_bssid(dev, selected->bssid); |
3353 | ieee80211_sta_def_wmm_params(dev, selected, 0); | ||
3277 | ieee80211_rx_bss_put(dev, selected); | 3354 | ieee80211_rx_bss_put(dev, selected); |
3278 | ifsta->state = IEEE80211_AUTHENTICATE; | 3355 | ifsta->state = IEEE80211_AUTHENTICATE; |
3279 | ieee80211_sta_reset_auth(dev, ifsta); | 3356 | ieee80211_sta_reset_auth(dev, ifsta); |
@@ -3448,43 +3525,10 @@ int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len) | |||
3448 | { | 3525 | { |
3449 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 3526 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
3450 | struct ieee80211_if_sta *ifsta; | 3527 | struct ieee80211_if_sta *ifsta; |
3451 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | ||
3452 | 3528 | ||
3453 | if (len > IEEE80211_MAX_SSID_LEN) | 3529 | if (len > IEEE80211_MAX_SSID_LEN) |
3454 | return -EINVAL; | 3530 | return -EINVAL; |
3455 | 3531 | ||
3456 | /* TODO: This should always be done for IBSS, even if IEEE80211_QOS is | ||
3457 | * not defined. */ | ||
3458 | if (local->ops->conf_tx) { | ||
3459 | struct ieee80211_tx_queue_params qparam; | ||
3460 | int i; | ||
3461 | |||
3462 | memset(&qparam, 0, sizeof(qparam)); | ||
3463 | |||
3464 | qparam.aifs = 2; | ||
3465 | |||
3466 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | ||
3467 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)) | ||
3468 | qparam.cw_min = 31; | ||
3469 | else | ||
3470 | qparam.cw_min = 15; | ||
3471 | |||
3472 | qparam.cw_max = 1023; | ||
3473 | qparam.txop = 0; | ||
3474 | |||
3475 | for (i = IEEE80211_TX_QUEUE_DATA0; i < NUM_TX_DATA_QUEUES; i++) | ||
3476 | local->ops->conf_tx(local_to_hw(local), | ||
3477 | i + IEEE80211_TX_QUEUE_DATA0, | ||
3478 | &qparam); | ||
3479 | |||
3480 | /* IBSS uses different parameters for Beacon sending */ | ||
3481 | qparam.cw_min++; | ||
3482 | qparam.cw_min *= 2; | ||
3483 | qparam.cw_min--; | ||
3484 | local->ops->conf_tx(local_to_hw(local), | ||
3485 | IEEE80211_TX_QUEUE_BEACON, &qparam); | ||
3486 | } | ||
3487 | |||
3488 | ifsta = &sdata->u.sta; | 3532 | ifsta = &sdata->u.sta; |
3489 | 3533 | ||
3490 | if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0) | 3534 | if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0) |
@@ -3596,6 +3640,9 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) | |||
3596 | 3640 | ||
3597 | if (local->sta_hw_scanning) { | 3641 | if (local->sta_hw_scanning) { |
3598 | local->sta_hw_scanning = 0; | 3642 | local->sta_hw_scanning = 0; |
3643 | if (ieee80211_hw_config(local)) | ||
3644 | printk(KERN_DEBUG "%s: failed to restore operational " | ||
3645 | "channel after scan\n", dev->name); | ||
3599 | /* Restart STA timer for HW scan case */ | 3646 | /* Restart STA timer for HW scan case */ |
3600 | rcu_read_lock(); | 3647 | rcu_read_lock(); |
3601 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | 3648 | list_for_each_entry_rcu(sdata, &local->interfaces, list) |
diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 3abe194e4d55..45d59f19c29f 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c | |||
@@ -214,6 +214,59 @@ void ieee80211_tkip_gen_rc4key(struct ieee80211_key *key, u8 *ta, | |||
214 | key->u.tkip.iv16, rc4key); | 214 | key->u.tkip.iv16, rc4key); |
215 | } | 215 | } |
216 | 216 | ||
217 | void ieee80211_get_tkip_key(struct ieee80211_key_conf *keyconf, | ||
218 | struct sk_buff *skb, enum ieee80211_tkip_key_type type, | ||
219 | u8 *outkey) | ||
220 | { | ||
221 | struct ieee80211_key *key = (struct ieee80211_key *) | ||
222 | container_of(keyconf, struct ieee80211_key, conf); | ||
223 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
224 | u8 *data = (u8 *) hdr; | ||
225 | u16 fc = le16_to_cpu(hdr->frame_control); | ||
226 | int hdr_len = ieee80211_get_hdrlen(fc); | ||
227 | u8 *ta = hdr->addr2; | ||
228 | u16 iv16; | ||
229 | u32 iv32; | ||
230 | |||
231 | iv16 = data[hdr_len] << 8; | ||
232 | iv16 += data[hdr_len + 2]; | ||
233 | iv32 = data[hdr_len + 4] + | ||
234 | (data[hdr_len + 5] >> 8) + | ||
235 | (data[hdr_len + 6] >> 16) + | ||
236 | (data[hdr_len + 7] >> 24); | ||
237 | |||
238 | #ifdef CONFIG_TKIP_DEBUG | ||
239 | printk(KERN_DEBUG "TKIP encrypt: iv16 = 0x%04x, iv32 = 0x%08x\n", | ||
240 | iv16, iv32); | ||
241 | |||
242 | if (iv32 != key->u.tkip.iv32) { | ||
243 | printk(KERN_DEBUG "skb: iv32 = 0x%08x key: iv32 = 0x%08x\n", | ||
244 | iv32, key->u.tkip.iv32); | ||
245 | printk(KERN_DEBUG "Wrap around of iv16 in the middle of a " | ||
246 | "fragmented packet\n"); | ||
247 | } | ||
248 | #endif /* CONFIG_TKIP_DEBUG */ | ||
249 | |||
250 | /* Update the p1k only when the iv16 in the packet wraps around, this | ||
251 | * might occur after the wrap around of iv16 in the key in case of | ||
252 | * fragmented packets. */ | ||
253 | if (iv16 == 0 || !key->u.tkip.tx_initialized) { | ||
254 | /* IV16 wrapped around - perform TKIP phase 1 */ | ||
255 | tkip_mixing_phase1(ta, &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY], | ||
256 | iv32, key->u.tkip.p1k); | ||
257 | key->u.tkip.tx_initialized = 1; | ||
258 | } | ||
259 | |||
260 | if (type == IEEE80211_TKIP_P1_KEY) { | ||
261 | memcpy(outkey, key->u.tkip.p1k, sizeof(u16) * 5); | ||
262 | return; | ||
263 | } | ||
264 | |||
265 | tkip_mixing_phase2(key->u.tkip.p1k, | ||
266 | &key->conf.key[ALG_TKIP_TEMP_ENCR_KEY], iv16, outkey); | ||
267 | } | ||
268 | EXPORT_SYMBOL(ieee80211_get_tkip_key); | ||
269 | |||
217 | /* Encrypt packet payload with TKIP using @key. @pos is a pointer to the | 270 | /* Encrypt packet payload with TKIP using @key. @pos is a pointer to the |
218 | * beginning of the buffer containing payload. This payload must include | 271 | * beginning of the buffer containing payload. This payload must include |
219 | * headroom of eight octets for IV and Ext. IV and taildroom of four octets | 272 | * headroom of eight octets for IV and Ext. IV and taildroom of four octets |
@@ -238,7 +291,7 @@ void ieee80211_tkip_encrypt_data(struct crypto_blkcipher *tfm, | |||
238 | int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | 291 | int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, |
239 | struct ieee80211_key *key, | 292 | struct ieee80211_key *key, |
240 | u8 *payload, size_t payload_len, u8 *ta, | 293 | u8 *payload, size_t payload_len, u8 *ta, |
241 | int only_iv, int queue, | 294 | u8 *ra, int only_iv, int queue, |
242 | u32 *out_iv32, u16 *out_iv16) | 295 | u32 *out_iv32, u16 *out_iv16) |
243 | { | 296 | { |
244 | u32 iv32; | 297 | u32 iv32; |
@@ -315,6 +368,19 @@ int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | |||
315 | printk("\n"); | 368 | printk("\n"); |
316 | } | 369 | } |
317 | #endif /* CONFIG_TKIP_DEBUG */ | 370 | #endif /* CONFIG_TKIP_DEBUG */ |
371 | if (key->local->ops->update_tkip_key && | ||
372 | key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) { | ||
373 | u8 bcast[ETH_ALEN] = | ||
374 | {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | ||
375 | u8 *sta_addr = key->sta->addr; | ||
376 | |||
377 | if (is_multicast_ether_addr(ra)) | ||
378 | sta_addr = bcast; | ||
379 | |||
380 | key->local->ops->update_tkip_key( | ||
381 | local_to_hw(key->local), &key->conf, | ||
382 | sta_addr, iv32, key->u.tkip.p1k_rx[queue]); | ||
383 | } | ||
318 | } | 384 | } |
319 | 385 | ||
320 | tkip_mixing_phase2(key->u.tkip.p1k_rx[queue], | 386 | tkip_mixing_phase2(key->u.tkip.p1k_rx[queue], |
diff --git a/net/mac80211/tkip.h b/net/mac80211/tkip.h index 73d8ef2a93b0..ffaee3253e19 100644 --- a/net/mac80211/tkip.h +++ b/net/mac80211/tkip.h | |||
@@ -31,7 +31,7 @@ enum { | |||
31 | int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, | 31 | int ieee80211_tkip_decrypt_data(struct crypto_blkcipher *tfm, |
32 | struct ieee80211_key *key, | 32 | struct ieee80211_key *key, |
33 | u8 *payload, size_t payload_len, u8 *ta, | 33 | u8 *payload, size_t payload_len, u8 *ta, |
34 | int only_iv, int queue, | 34 | u8 *ra, int only_iv, int queue, |
35 | u32 *out_iv32, u16 *out_iv16); | 35 | u32 *out_iv32, u16 *out_iv16); |
36 | 36 | ||
37 | #endif /* TKIP_H */ | 37 | #endif /* TKIP_H */ |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index df0b7341efc8..45709ada8fee 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -312,7 +312,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
312 | res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, | 312 | res = ieee80211_tkip_decrypt_data(rx->local->wep_rx_tfm, |
313 | key, skb->data + hdrlen, | 313 | key, skb->data + hdrlen, |
314 | skb->len - hdrlen, rx->sta->addr, | 314 | skb->len - hdrlen, rx->sta->addr, |
315 | hwaccel, rx->queue, | 315 | hdr->addr1, hwaccel, rx->queue, |
316 | &rx->tkip_iv32, | 316 | &rx->tkip_iv32, |
317 | &rx->tkip_iv16); | 317 | &rx->tkip_iv16); |
318 | if (res != TKIP_DECRYPT_OK || wpa_test) { | 318 | if (res != TKIP_DECRYPT_OK || wpa_test) { |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 77336c22fcf2..f3e623df3515 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -33,6 +33,29 @@ int ieee80211_frequency_to_channel(int freq) | |||
33 | } | 33 | } |
34 | EXPORT_SYMBOL(ieee80211_frequency_to_channel); | 34 | EXPORT_SYMBOL(ieee80211_frequency_to_channel); |
35 | 35 | ||
36 | struct ieee80211_channel *ieee80211_get_channel(struct wiphy *wiphy, | ||
37 | int freq) | ||
38 | { | ||
39 | enum ieee80211_band band; | ||
40 | struct ieee80211_supported_band *sband; | ||
41 | int i; | ||
42 | |||
43 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) { | ||
44 | sband = wiphy->bands[band]; | ||
45 | |||
46 | if (!sband) | ||
47 | continue; | ||
48 | |||
49 | for (i = 0; i < sband->n_channels; i++) { | ||
50 | if (sband->channels[i].center_freq == freq) | ||
51 | return &sband->channels[i]; | ||
52 | } | ||
53 | } | ||
54 | |||
55 | return NULL; | ||
56 | } | ||
57 | EXPORT_SYMBOL(ieee80211_get_channel); | ||
58 | |||
36 | static void set_mandatory_flags_band(struct ieee80211_supported_band *sband, | 59 | static void set_mandatory_flags_band(struct ieee80211_supported_band *sband, |
37 | enum ieee80211_band band) | 60 | enum ieee80211_band band) |
38 | { | 61 | { |