2008-01-24 19:38:38 +01:00
/*
* Wireless utility functions
*
2009-04-20 14:31:42 +02:00
* Copyright 2007 - 2009 Johannes Berg < johannes @ sipsolutions . net >
2008-01-24 19:38:38 +01:00
*/
2009-04-20 14:31:42 +02:00
# include <linux/bitops.h>
# include <net/cfg80211.h>
2008-01-24 19:38:38 +01:00
# include "core.h"
2008-10-29 20:00:45 +01:00
struct ieee80211_rate *
ieee80211_get_response_rate ( struct ieee80211_supported_band * sband ,
2009-01-21 15:13:48 +01:00
u32 basic_rates , int bitrate )
2008-10-29 20:00:45 +01:00
{
struct ieee80211_rate * result = & sband - > bitrates [ 0 ] ;
int i ;
for ( i = 0 ; i < sband - > n_bitrates ; i + + ) {
if ( ! ( basic_rates & BIT ( i ) ) )
continue ;
if ( sband - > bitrates [ i ] . bitrate > bitrate )
continue ;
result = & sband - > bitrates [ i ] ;
}
return result ;
}
EXPORT_SYMBOL ( ieee80211_get_response_rate ) ;
2008-01-24 19:38:38 +01:00
int ieee80211_channel_to_frequency ( int chan )
{
if ( chan < 14 )
return 2407 + chan * 5 ;
if ( chan = = 14 )
return 2484 ;
/* FIXME: 802.11j 17.3.8.3.2 */
return ( chan + 1000 ) * 5 ;
}
EXPORT_SYMBOL ( ieee80211_channel_to_frequency ) ;
int ieee80211_frequency_to_channel ( int freq )
{
if ( freq = = 2484 )
return 14 ;
if ( freq < 2484 )
return ( freq - 2407 ) / 5 ;
/* FIXME: 802.11j 17.3.8.3.2 */
return freq / 5 - 1000 ;
}
EXPORT_SYMBOL ( ieee80211_frequency_to_channel ) ;
2008-03-26 14:14:55 +01:00
struct ieee80211_channel * __ieee80211_get_channel ( struct wiphy * wiphy ,
int freq )
2008-03-16 18:34:33 +01:00
{
enum ieee80211_band band ;
struct ieee80211_supported_band * sband ;
int i ;
for ( band = 0 ; band < IEEE80211_NUM_BANDS ; band + + ) {
sband = wiphy - > bands [ band ] ;
if ( ! sband )
continue ;
for ( i = 0 ; i < sband - > n_channels ; i + + ) {
if ( sband - > channels [ i ] . center_freq = = freq )
return & sband - > channels [ i ] ;
}
}
return NULL ;
}
2008-03-26 14:14:55 +01:00
EXPORT_SYMBOL ( __ieee80211_get_channel ) ;
2008-03-16 18:34:33 +01:00
2008-01-24 19:38:38 +01:00
static void set_mandatory_flags_band ( struct ieee80211_supported_band * sband ,
enum ieee80211_band band )
{
int i , want ;
switch ( band ) {
case IEEE80211_BAND_5GHZ :
want = 3 ;
for ( i = 0 ; i < sband - > n_bitrates ; i + + ) {
if ( sband - > bitrates [ i ] . bitrate = = 60 | |
sband - > bitrates [ i ] . bitrate = = 120 | |
sband - > bitrates [ i ] . bitrate = = 240 ) {
sband - > bitrates [ i ] . flags | =
IEEE80211_RATE_MANDATORY_A ;
want - - ;
}
}
WARN_ON ( want ) ;
break ;
case IEEE80211_BAND_2GHZ :
want = 7 ;
for ( i = 0 ; i < sband - > n_bitrates ; i + + ) {
if ( sband - > bitrates [ i ] . bitrate = = 10 ) {
sband - > bitrates [ i ] . flags | =
IEEE80211_RATE_MANDATORY_B |
IEEE80211_RATE_MANDATORY_G ;
want - - ;
}
if ( sband - > bitrates [ i ] . bitrate = = 20 | |
sband - > bitrates [ i ] . bitrate = = 55 | |
sband - > bitrates [ i ] . bitrate = = 110 | |
sband - > bitrates [ i ] . bitrate = = 60 | |
sband - > bitrates [ i ] . bitrate = = 120 | |
sband - > bitrates [ i ] . bitrate = = 240 ) {
sband - > bitrates [ i ] . flags | =
IEEE80211_RATE_MANDATORY_G ;
want - - ;
}
2008-01-30 17:36:10 +01:00
if ( sband - > bitrates [ i ] . bitrate ! = 10 & &
sband - > bitrates [ i ] . bitrate ! = 20 & &
sband - > bitrates [ i ] . bitrate ! = 55 & &
sband - > bitrates [ i ] . bitrate ! = 110 )
2008-01-24 19:38:38 +01:00
sband - > bitrates [ i ] . flags | =
IEEE80211_RATE_ERP_G ;
}
2008-02-02 23:53:10 +01:00
WARN_ON ( want ! = 0 & & want ! = 3 & & want ! = 6 ) ;
2008-01-24 19:38:38 +01:00
break ;
case IEEE80211_NUM_BANDS :
WARN_ON ( 1 ) ;
break ;
}
}
void ieee80211_set_bitrate_flags ( struct wiphy * wiphy )
{
enum ieee80211_band band ;
for ( band = 0 ; band < IEEE80211_NUM_BANDS ; band + + )
if ( wiphy - > bands [ band ] )
set_mandatory_flags_band ( wiphy - > bands [ band ] , band ) ;
}
2009-05-11 13:54:58 +02:00
int cfg80211_validate_key_settings ( struct key_params * params , int key_idx ,
const u8 * mac_addr )
{
if ( key_idx > 5 )
return - EINVAL ;
/*
* Disallow pairwise keys with non - zero index unless it ' s WEP
* ( because current deployments use pairwise WEP keys with
* non - zero indizes but 802.11 i clearly specifies to use zero )
*/
if ( mac_addr & & key_idx & &
params - > cipher ! = WLAN_CIPHER_SUITE_WEP40 & &
params - > cipher ! = WLAN_CIPHER_SUITE_WEP104 )
return - EINVAL ;
/* TODO: add definitions for the lengths to linux/ieee80211.h */
switch ( params - > cipher ) {
case WLAN_CIPHER_SUITE_WEP40 :
if ( params - > key_len ! = 5 )
return - EINVAL ;
break ;
case WLAN_CIPHER_SUITE_TKIP :
if ( params - > key_len ! = 32 )
return - EINVAL ;
break ;
case WLAN_CIPHER_SUITE_CCMP :
if ( params - > key_len ! = 16 )
return - EINVAL ;
break ;
case WLAN_CIPHER_SUITE_WEP104 :
if ( params - > key_len ! = 13 )
return - EINVAL ;
break ;
case WLAN_CIPHER_SUITE_AES_CMAC :
if ( params - > key_len ! = 16 )
return - EINVAL ;
break ;
default :
return - EINVAL ;
}
return 0 ;
}