2007-02-10 12:25:27 -02:00
/* Copyright (C) 2006, Red Hat, Inc. */
# include <linux/bitops.h>
# include <net/ieee80211.h>
2007-05-25 17:28:30 -04:00
# include <linux/etherdevice.h>
2007-02-10 12:25:27 -02:00
# include "assoc.h"
# include "join.h"
# include "decl.h"
# include "hostcmd.h"
# include "host.h"
static const u8 bssid_any [ ETH_ALEN ] = { 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF } ;
static const u8 bssid_off [ ETH_ALEN ] = { 0x00 , 0x00 , 0x00 , 0x00 , 0x00 , 0x00 } ;
2007-05-25 17:09:41 -04:00
/* From ieee80211_module.c */
static const char * libertas_escape_essid ( const char * essid , u8 essid_len )
{
static char escaped [ IW_ESSID_MAX_SIZE * 2 + 1 ] ;
const char * s = essid ;
char * d = escaped ;
if ( ieee80211_is_empty_essid ( essid , essid_len ) )
return " " ;
essid_len = min ( essid_len , ( u8 ) IW_ESSID_MAX_SIZE ) ;
while ( essid_len - - ) {
if ( * s = = ' \0 ' ) {
* d + + = ' \\ ' ;
* d + + = ' 0 ' ;
s + + ;
} else {
* d + + = * s + + ;
}
}
* d = ' \0 ' ;
return escaped ;
}
static void print_assoc_req ( const char * extra , struct assoc_request * assoc_req )
{
lbs_deb_assoc (
" #### Association Request: %s \n "
" flags: 0x%08lX \n "
" SSID: '%s' \n "
" channel: %d \n "
" band: %d \n "
" mode: %d \n "
" BSSID: " MAC_FMT " \n "
" WPA: %d \n "
" WPA2: %d \n "
" WEP status: %d \n "
" auth: %d \n "
" auth_alg: %d \n "
" encmode: %d \n " ,
extra , assoc_req - > flags ,
libertas_escape_essid ( assoc_req - > ssid . ssid , assoc_req - > ssid . ssidlength ) ,
assoc_req - > channel , assoc_req - > band , assoc_req - > mode ,
MAC_ARG ( assoc_req - > bssid ) , assoc_req - > secinfo . WPAenabled ,
assoc_req - > secinfo . WPA2enabled , assoc_req - > secinfo . WEPstatus ,
assoc_req - > secinfo . authmode , assoc_req - > secinfo . auth1xalg ,
assoc_req - > secinfo . Encryptionmode ) ;
}
2007-02-10 12:25:27 -02:00
static int assoc_helper_essid ( wlan_private * priv ,
struct assoc_request * assoc_req )
{
wlan_adapter * adapter = priv - > adapter ;
int ret = 0 ;
2007-05-25 16:15:56 -04:00
struct bss_descriptor * bss ;
2007-05-25 22:30:48 -04:00
int channel = - 1 ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_ASSOC ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 16:46:33 -04:00
/* FIXME: take channel into account when picking SSIDs if a channel
* is set .
*/
2007-05-25 22:30:48 -04:00
if ( test_bit ( ASSOC_FLAG_CHANNEL , & assoc_req - > flags ) )
channel = assoc_req - > channel ;
2007-05-25 11:27:16 -04:00
lbs_deb_assoc ( " New SSID requested: %s \n " , assoc_req - > ssid . ssid ) ;
2007-05-10 22:58:02 -04:00
if ( assoc_req - > mode = = IW_MODE_INFRA ) {
2007-02-10 12:25:27 -02:00
if ( adapter - > prescan ) {
2007-05-25 16:25:21 -04:00
libertas_send_specific_SSID_scan ( priv , & assoc_req - > ssid , 0 ) ;
2007-02-10 12:25:27 -02:00
}
2007-05-25 16:15:56 -04:00
bss = libertas_find_SSID_in_list ( adapter , & assoc_req - > ssid ,
2007-05-25 22:30:48 -04:00
NULL , IW_MODE_INFRA , channel ) ;
2007-05-25 16:15:56 -04:00
if ( bss ! = NULL ) {
lbs_deb_assoc ( " SSID found in scan list, associating \n " ) ;
2007-05-25 17:09:41 -04:00
memcpy ( & assoc_req - > bss , bss , sizeof ( struct bss_descriptor ) ) ;
ret = wlan_associate ( priv , assoc_req ) ;
2007-02-10 12:25:27 -02:00
} else {
2007-05-25 11:27:16 -04:00
lbs_deb_assoc ( " SSID '%s' not found; cannot associate \n " ,
2007-02-10 12:25:27 -02:00
assoc_req - > ssid . ssid ) ;
}
2007-05-10 22:58:02 -04:00
} else if ( assoc_req - > mode = = IW_MODE_ADHOC ) {
2007-02-10 12:25:27 -02:00
/* Scan for the network, do not save previous results. Stale
* scan data will cause us to join a non - existant adhoc network
*/
2007-05-25 16:25:21 -04:00
libertas_send_specific_SSID_scan ( priv , & assoc_req - > ssid , 1 ) ;
2007-02-10 12:25:27 -02:00
/* Search for the requested SSID in the scan table */
2007-05-25 16:15:56 -04:00
bss = libertas_find_SSID_in_list ( adapter , & assoc_req - > ssid , NULL ,
2007-05-25 22:30:48 -04:00
IW_MODE_ADHOC , channel ) ;
2007-05-25 16:15:56 -04:00
if ( bss ! = NULL ) {
lbs_deb_assoc ( " SSID found joining \n " ) ;
2007-05-25 17:09:41 -04:00
memcpy ( & assoc_req - > bss , bss , sizeof ( struct bss_descriptor ) ) ;
libertas_join_adhoc_network ( priv , assoc_req ) ;
2007-02-10 12:25:27 -02:00
} else {
/* else send START command */
2007-05-25 11:27:16 -04:00
lbs_deb_assoc ( " SSID not found in list, so creating adhoc "
2007-02-10 12:25:27 -02:00
" with SSID '%s' \n " , assoc_req - > ssid . ssid ) ;
2007-05-25 17:09:41 -04:00
memcpy ( & assoc_req - > bss . ssid , & assoc_req - > ssid ,
sizeof ( struct WLAN_802_11_SSID ) ) ;
libertas_start_adhoc_network ( priv , assoc_req ) ;
2007-02-10 12:25:27 -02:00
}
}
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_ASSOC , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
static int assoc_helper_bssid ( wlan_private * priv ,
struct assoc_request * assoc_req )
{
wlan_adapter * adapter = priv - > adapter ;
2007-05-25 16:15:56 -04:00
int ret = 0 ;
struct bss_descriptor * bss ;
2007-02-10 12:25:27 -02:00
2007-05-25 22:54:50 -04:00
lbs_deb_enter_args ( LBS_DEB_ASSOC , " BSSID " MAC_FMT " \n " ,
2007-02-10 12:25:27 -02:00
MAC_ARG ( assoc_req - > bssid ) ) ;
/* Search for index position in list for requested MAC */
2007-05-25 16:15:56 -04:00
bss = libertas_find_BSSID_in_list ( adapter , assoc_req - > bssid ,
2007-02-10 12:25:27 -02:00
assoc_req - > mode ) ;
2007-05-25 16:15:56 -04:00
if ( bss = = NULL ) {
2007-05-25 11:27:16 -04:00
lbs_deb_assoc ( " ASSOC: WAP: BSSID " MAC_FMT " not found, "
2007-02-10 12:25:27 -02:00
" cannot associate. \n " , MAC_ARG ( assoc_req - > bssid ) ) ;
goto out ;
}
2007-05-25 17:09:41 -04:00
memcpy ( & assoc_req - > bss , bss , sizeof ( struct bss_descriptor ) ) ;
2007-05-10 22:58:02 -04:00
if ( assoc_req - > mode = = IW_MODE_INFRA ) {
2007-05-25 17:09:41 -04:00
ret = wlan_associate ( priv , assoc_req ) ;
2007-05-25 16:15:56 -04:00
lbs_deb_assoc ( " ASSOC: wlan_associate(bssid) returned %d \n " , ret ) ;
2007-05-10 22:58:02 -04:00
} else if ( assoc_req - > mode = = IW_MODE_ADHOC ) {
2007-05-25 17:09:41 -04:00
libertas_join_adhoc_network ( priv , assoc_req ) ;
2007-02-10 12:25:27 -02:00
}
out :
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_ASSOC , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
static int assoc_helper_associate ( wlan_private * priv ,
struct assoc_request * assoc_req )
{
int ret = 0 , done = 0 ;
/* If we're given and 'any' BSSID, try associating based on SSID */
if ( test_bit ( ASSOC_FLAG_BSSID , & assoc_req - > flags ) ) {
2007-05-25 17:28:30 -04:00
if ( compare_ether_addr ( bssid_any , assoc_req - > bssid )
& & compare_ether_addr ( bssid_off , assoc_req - > bssid ) ) {
2007-02-10 12:25:27 -02:00
ret = assoc_helper_bssid ( priv , assoc_req ) ;
done = 1 ;
if ( ret ) {
2007-05-25 11:27:16 -04:00
lbs_deb_assoc ( " ASSOC: bssid: ret = %d \n " , ret ) ;
2007-02-10 12:25:27 -02:00
}
}
}
if ( ! done & & test_bit ( ASSOC_FLAG_SSID , & assoc_req - > flags ) ) {
ret = assoc_helper_essid ( priv , assoc_req ) ;
if ( ret ) {
2007-05-25 11:27:16 -04:00
lbs_deb_assoc ( " ASSOC: bssid: ret = %d \n " , ret ) ;
2007-02-10 12:25:27 -02:00
}
}
return ret ;
}
static int assoc_helper_mode ( wlan_private * priv ,
struct assoc_request * assoc_req )
{
wlan_adapter * adapter = priv - > adapter ;
int ret = 0 ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_ASSOC ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
if ( assoc_req - > mode = = adapter - > mode )
goto done ;
2007-02-10 12:25:27 -02:00
2007-05-10 22:58:02 -04:00
if ( assoc_req - > mode = = IW_MODE_INFRA ) {
2007-02-10 12:25:27 -02:00
if ( adapter - > psstate ! = PS_STATE_FULL_POWER )
libertas_ps_wakeup ( priv , cmd_option_waitforrsp ) ;
adapter - > psmode = wlan802_11powermodecam ;
}
2007-05-10 22:58:02 -04:00
adapter - > mode = assoc_req - > mode ;
2007-02-10 12:25:27 -02:00
ret = libertas_prepare_and_send_command ( priv ,
cmd_802_11_snmp_mib ,
0 , cmd_option_waitforrsp ,
OID_802_11_INFRASTRUCTURE_MODE ,
2007-05-10 22:58:02 -04:00
( void * ) ( size_t ) assoc_req - > mode ) ;
2007-02-10 12:25:27 -02:00
2007-05-25 11:27:16 -04:00
done :
lbs_deb_leave_args ( LBS_DEB_ASSOC , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
2007-05-25 16:46:33 -04:00
static int update_channel ( wlan_private * priv )
{
/* the channel in f/w could be out of sync, get the current channel */
return libertas_prepare_and_send_command ( priv , cmd_802_11_rf_channel ,
cmd_opt_802_11_rf_channel_get ,
cmd_option_waitforrsp , 0 , NULL ) ;
}
static int assoc_helper_channel ( wlan_private * priv ,
struct assoc_request * assoc_req )
{
wlan_adapter * adapter = priv - > adapter ;
int ret = 0 ;
lbs_deb_enter ( LBS_DEB_ASSOC ) ;
ret = update_channel ( priv ) ;
if ( ret < 0 ) {
lbs_deb_assoc ( " ASSOC: channel: error getting channel. " ) ;
}
if ( assoc_req - > channel = = adapter - > curbssparams . channel )
goto done ;
lbs_deb_assoc ( " ASSOC: channel: %d -> %d \n " ,
adapter - > curbssparams . channel , assoc_req - > channel ) ;
ret = libertas_prepare_and_send_command ( priv , cmd_802_11_rf_channel ,
cmd_opt_802_11_rf_channel_set ,
cmd_option_waitforrsp , 0 , & assoc_req - > channel ) ;
if ( ret < 0 ) {
lbs_deb_assoc ( " ASSOC: channel: error setting channel. " ) ;
}
ret = update_channel ( priv ) ;
if ( ret < 0 ) {
lbs_deb_assoc ( " ASSOC: channel: error getting channel. " ) ;
}
if ( assoc_req - > channel ! = adapter - > curbssparams . channel ) {
lbs_deb_assoc ( " ASSOC: channel: failed to update channel to %d " ,
assoc_req - > channel ) ;
goto done ;
}
if ( assoc_req - > secinfo . wep_enabled
& & ( assoc_req - > wep_keys [ 0 ] . len
| | assoc_req - > wep_keys [ 1 ] . len
| | assoc_req - > wep_keys [ 2 ] . len
| | assoc_req - > wep_keys [ 3 ] . len ) ) {
/* Make sure WEP keys are re-sent to firmware */
set_bit ( ASSOC_FLAG_WEP_KEYS , & assoc_req - > flags ) ;
}
/* Must restart/rejoin adhoc networks after channel change */
set_bit ( ASSOC_FLAG_SSID , & assoc_req - > flags ) ;
done :
lbs_deb_leave_args ( LBS_DEB_ASSOC , " ret %d " , ret ) ;
return ret ;
}
2007-02-10 12:25:27 -02:00
static int assoc_helper_wep_keys ( wlan_private * priv ,
struct assoc_request * assoc_req )
{
wlan_adapter * adapter = priv - > adapter ;
int i ;
int ret = 0 ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_ASSOC ) ;
2007-02-10 12:25:27 -02:00
/* Set or remove WEP keys */
if ( assoc_req - > wep_keys [ 0 ] . len
| | assoc_req - > wep_keys [ 1 ] . len
| | assoc_req - > wep_keys [ 2 ] . len
| | assoc_req - > wep_keys [ 3 ] . len ) {
ret = libertas_prepare_and_send_command ( priv ,
cmd_802_11_set_wep ,
cmd_act_add ,
cmd_option_waitforrsp ,
0 , assoc_req ) ;
} else {
ret = libertas_prepare_and_send_command ( priv ,
cmd_802_11_set_wep ,
cmd_act_remove ,
cmd_option_waitforrsp ,
0 , NULL ) ;
}
if ( ret )
goto out ;
/* enable/disable the MAC's WEP packet filter */
2007-05-10 22:57:23 -04:00
if ( assoc_req - > secinfo . wep_enabled )
2007-02-10 12:25:27 -02:00
adapter - > currentpacketfilter | = cmd_act_mac_wep_enable ;
else
adapter - > currentpacketfilter & = ~ cmd_act_mac_wep_enable ;
ret = libertas_set_mac_packet_filter ( priv ) ;
if ( ret )
goto out ;
mutex_lock ( & adapter - > lock ) ;
/* Copy WEP keys into adapter wep key fields */
for ( i = 0 ; i < 4 ; i + + ) {
memcpy ( & adapter - > wep_keys [ i ] , & assoc_req - > wep_keys [ i ] ,
sizeof ( struct WLAN_802_11_KEY ) ) ;
}
adapter - > wep_tx_keyidx = assoc_req - > wep_tx_keyidx ;
mutex_unlock ( & adapter - > lock ) ;
out :
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_ASSOC , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
static int assoc_helper_secinfo ( wlan_private * priv ,
struct assoc_request * assoc_req )
{
wlan_adapter * adapter = priv - > adapter ;
int ret = 0 ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_ASSOC ) ;
2007-02-10 12:25:27 -02:00
memcpy ( & adapter - > secinfo , & assoc_req - > secinfo ,
sizeof ( struct wlan_802_11_security ) ) ;
ret = libertas_set_mac_packet_filter ( priv ) ;
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_ASSOC , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
static int assoc_helper_wpa_keys ( wlan_private * priv ,
struct assoc_request * assoc_req )
{
int ret = 0 ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_ASSOC ) ;
2007-02-10 12:25:27 -02:00
/* enable/Disable RSN */
ret = libertas_prepare_and_send_command ( priv ,
cmd_802_11_enable_rsn ,
cmd_act_set ,
cmd_option_waitforrsp ,
0 , assoc_req ) ;
if ( ret )
goto out ;
ret = libertas_prepare_and_send_command ( priv ,
cmd_802_11_key_material ,
cmd_act_set ,
cmd_option_waitforrsp ,
0 , assoc_req ) ;
out :
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_ASSOC , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
static int assoc_helper_wpa_ie ( wlan_private * priv ,
struct assoc_request * assoc_req )
{
wlan_adapter * adapter = priv - > adapter ;
int ret = 0 ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_ASSOC ) ;
2007-02-10 12:25:27 -02:00
if ( assoc_req - > secinfo . WPAenabled | | assoc_req - > secinfo . WPA2enabled ) {
memcpy ( & adapter - > wpa_ie , & assoc_req - > wpa_ie , assoc_req - > wpa_ie_len ) ;
adapter - > wpa_ie_len = assoc_req - > wpa_ie_len ;
} else {
memset ( & adapter - > wpa_ie , 0 , MAX_WPA_IE_LEN ) ;
adapter - > wpa_ie_len = 0 ;
}
2007-05-25 11:27:16 -04:00
lbs_deb_leave_args ( LBS_DEB_ASSOC , " ret %d " , ret ) ;
2007-02-10 12:25:27 -02:00
return ret ;
}
static int should_deauth_infrastructure ( wlan_adapter * adapter ,
struct assoc_request * assoc_req )
{
if ( adapter - > connect_status ! = libertas_connected )
return 0 ;
if ( test_bit ( ASSOC_FLAG_SSID , & assoc_req - > flags ) ) {
2007-05-25 11:27:16 -04:00
lbs_deb_assoc ( " Deauthenticating due to new SSID in "
2007-02-10 12:25:27 -02:00
" configuration request. \n " ) ;
return 1 ;
}
if ( test_bit ( ASSOC_FLAG_SECINFO , & assoc_req - > flags ) ) {
2007-05-10 22:56:42 -04:00
if ( adapter - > secinfo . auth_mode ! = assoc_req - > secinfo . auth_mode ) {
2007-05-25 11:27:16 -04:00
lbs_deb_assoc ( " Deauthenticating due to updated security "
2007-02-10 12:25:27 -02:00
" info in configuration request. \n " ) ;
return 1 ;
}
}
if ( test_bit ( ASSOC_FLAG_BSSID , & assoc_req - > flags ) ) {
2007-05-25 11:27:16 -04:00
lbs_deb_assoc ( " Deauthenticating due to new BSSID in "
2007-02-10 12:25:27 -02:00
" configuration request. \n " ) ;
return 1 ;
}
/* FIXME: deal with 'auto' mode somehow */
if ( test_bit ( ASSOC_FLAG_MODE , & assoc_req - > flags ) ) {
2007-05-10 22:58:02 -04:00
if ( assoc_req - > mode ! = IW_MODE_INFRA )
2007-02-10 12:25:27 -02:00
return 1 ;
}
return 0 ;
}
static int should_stop_adhoc ( wlan_adapter * adapter ,
struct assoc_request * assoc_req )
{
if ( adapter - > connect_status ! = libertas_connected )
return 0 ;
if ( adapter - > curbssparams . ssid . ssidlength ! = assoc_req - > ssid . ssidlength )
return 1 ;
if ( memcmp ( adapter - > curbssparams . ssid . ssid , assoc_req - > ssid . ssid ,
2007-05-10 22:52:37 -04:00
adapter - > curbssparams . ssid . ssidlength ) )
2007-02-10 12:25:27 -02:00
return 1 ;
/* FIXME: deal with 'auto' mode somehow */
if ( test_bit ( ASSOC_FLAG_MODE , & assoc_req - > flags ) ) {
2007-05-10 22:58:02 -04:00
if ( assoc_req - > mode ! = IW_MODE_ADHOC )
2007-02-10 12:25:27 -02:00
return 1 ;
}
2007-05-25 16:46:33 -04:00
if ( test_bit ( ASSOC_FLAG_CHANNEL , & assoc_req - > flags ) ) {
if ( assoc_req - > channel ! = adapter - > curbssparams . channel )
return 1 ;
}
2007-02-10 12:25:27 -02:00
return 0 ;
}
2007-05-24 23:41:15 -04:00
void libertas_association_worker ( struct work_struct * work )
2007-02-10 12:25:27 -02:00
{
wlan_private * priv = container_of ( work , wlan_private , assoc_work . work ) ;
wlan_adapter * adapter = priv - > adapter ;
struct assoc_request * assoc_req = NULL ;
int ret = 0 ;
int find_any_ssid = 0 ;
2007-05-25 11:27:16 -04:00
lbs_deb_enter ( LBS_DEB_ASSOC ) ;
2007-02-10 12:25:27 -02:00
mutex_lock ( & adapter - > lock ) ;
2007-05-25 17:09:41 -04:00
assoc_req = adapter - > pending_assoc_req ;
adapter - > pending_assoc_req = NULL ;
adapter - > in_progress_assoc_req = assoc_req ;
2007-02-10 12:25:27 -02:00
mutex_unlock ( & adapter - > lock ) ;
2007-05-25 11:27:16 -04:00
if ( ! assoc_req )
goto done ;
2007-02-10 12:25:27 -02:00
2007-05-25 17:09:41 -04:00
print_assoc_req ( __func__ , assoc_req ) ;
2007-02-10 12:25:27 -02:00
/* If 'any' SSID was specified, find an SSID to associate with */
if ( test_bit ( ASSOC_FLAG_SSID , & assoc_req - > flags )
& & ! assoc_req - > ssid . ssidlength )
find_any_ssid = 1 ;
/* But don't use 'any' SSID if there's a valid locked BSSID to use */
if ( test_bit ( ASSOC_FLAG_BSSID , & assoc_req - > flags ) ) {
2007-05-25 17:28:30 -04:00
if ( compare_ether_addr ( assoc_req - > bssid , bssid_any )
& & compare_ether_addr ( assoc_req - > bssid , bssid_off ) )
2007-02-10 12:25:27 -02:00
find_any_ssid = 0 ;
}
if ( find_any_ssid ) {
2007-05-10 22:58:02 -04:00
u8 new_mode ;
2007-02-10 12:25:27 -02:00
ret = libertas_find_best_network_SSID ( priv , & assoc_req - > ssid ,
assoc_req - > mode , & new_mode ) ;
if ( ret ) {
2007-05-25 11:27:16 -04:00
lbs_deb_assoc ( " Could not find best network \n " ) ;
2007-02-10 12:25:27 -02:00
ret = - ENETUNREACH ;
goto out ;
}
/* Ensure we switch to the mode of the AP */
2007-05-10 22:58:02 -04:00
if ( assoc_req - > mode = = IW_MODE_AUTO ) {
2007-02-10 12:25:27 -02:00
set_bit ( ASSOC_FLAG_MODE , & assoc_req - > flags ) ;
assoc_req - > mode = new_mode ;
}
}
/*
* Check if the attributes being changing require deauthentication
* from the currently associated infrastructure access point .
*/
2007-05-10 22:58:02 -04:00
if ( adapter - > mode = = IW_MODE_INFRA ) {
2007-02-10 12:25:27 -02:00
if ( should_deauth_infrastructure ( adapter , assoc_req ) ) {
ret = libertas_send_deauthentication ( priv ) ;
if ( ret ) {
2007-05-25 11:27:16 -04:00
lbs_deb_assoc ( " Deauthentication due to new "
2007-02-10 12:25:27 -02:00
" configuration request failed: %d \n " ,
ret ) ;
}
}
2007-05-10 22:58:02 -04:00
} else if ( adapter - > mode = = IW_MODE_ADHOC ) {
2007-02-10 12:25:27 -02:00
if ( should_stop_adhoc ( adapter , assoc_req ) ) {
ret = libertas_stop_adhoc_network ( priv ) ;
if ( ret ) {
2007-05-25 11:27:16 -04:00
lbs_deb_assoc ( " Teardown of AdHoc network due to "
2007-02-10 12:25:27 -02:00
" new configuration request failed: %d \n " ,
ret ) ;
}
}
}
/* Send the various configuration bits to the firmware */
if ( test_bit ( ASSOC_FLAG_MODE , & assoc_req - > flags ) ) {
ret = assoc_helper_mode ( priv , assoc_req ) ;
if ( ret ) {
2007-05-25 11:27:16 -04:00
lbs_deb_assoc ( " ASSOC(:%d) mode: ret = %d \n " , __LINE__ , ret ) ;
2007-02-10 12:25:27 -02:00
goto out ;
}
}
2007-05-25 16:46:33 -04:00
if ( test_bit ( ASSOC_FLAG_CHANNEL , & assoc_req - > flags ) ) {
ret = assoc_helper_channel ( priv , assoc_req ) ;
if ( ret ) {
lbs_deb_assoc ( " ASSOC(:%d) channel: ret = %d \n " ,
__LINE__ , ret ) ;
goto out ;
}
}
2007-02-10 12:25:27 -02:00
if ( test_bit ( ASSOC_FLAG_WEP_KEYS , & assoc_req - > flags )
| | test_bit ( ASSOC_FLAG_WEP_TX_KEYIDX , & assoc_req - > flags ) ) {
ret = assoc_helper_wep_keys ( priv , assoc_req ) ;
if ( ret ) {
2007-05-25 11:27:16 -04:00
lbs_deb_assoc ( " ASSOC(:%d) wep_keys: ret = %d \n " , __LINE__ , ret ) ;
2007-02-10 12:25:27 -02:00
goto out ;
}
}
if ( test_bit ( ASSOC_FLAG_SECINFO , & assoc_req - > flags ) ) {
ret = assoc_helper_secinfo ( priv , assoc_req ) ;
if ( ret ) {
2007-05-25 11:27:16 -04:00
lbs_deb_assoc ( " ASSOC(:%d) secinfo: ret = %d \n " , __LINE__ , ret ) ;
2007-02-10 12:25:27 -02:00
goto out ;
}
}
if ( test_bit ( ASSOC_FLAG_WPA_IE , & assoc_req - > flags ) ) {
ret = assoc_helper_wpa_ie ( priv , assoc_req ) ;
if ( ret ) {
2007-05-25 11:27:16 -04:00
lbs_deb_assoc ( " ASSOC(:%d) wpa_ie: ret = %d \n " , __LINE__ , ret ) ;
2007-02-10 12:25:27 -02:00
goto out ;
}
}
if ( test_bit ( ASSOC_FLAG_WPA_MCAST_KEY , & assoc_req - > flags )
| | test_bit ( ASSOC_FLAG_WPA_UCAST_KEY , & assoc_req - > flags ) ) {
ret = assoc_helper_wpa_keys ( priv , assoc_req ) ;
if ( ret ) {
2007-05-25 11:27:16 -04:00
lbs_deb_assoc ( " ASSOC(:%d) wpa_keys: ret = %d \n " , __LINE__ , ret ) ;
2007-02-10 12:25:27 -02:00
goto out ;
}
}
/* SSID/BSSID should be the _last_ config option set, because they
* trigger the association attempt .
*/
if ( test_bit ( ASSOC_FLAG_BSSID , & assoc_req - > flags )
| | test_bit ( ASSOC_FLAG_SSID , & assoc_req - > flags ) ) {
int success = 1 ;
ret = assoc_helper_associate ( priv , assoc_req ) ;
if ( ret ) {
2007-05-25 11:27:16 -04:00
lbs_deb_assoc ( " ASSOC: association attempt unsuccessful: %d \n " ,
2007-02-10 12:25:27 -02:00
ret ) ;
success = 0 ;
}
if ( adapter - > connect_status ! = libertas_connected ) {
2007-05-25 11:27:16 -04:00
lbs_deb_assoc ( " ASSOC: assoication attempt unsuccessful, "
2007-02-10 12:25:27 -02:00
" not connected. \n " ) ;
success = 0 ;
}
if ( success ) {
2007-05-25 11:27:16 -04:00
lbs_deb_assoc ( " ASSOC: association attempt successful. "
2007-02-10 12:25:27 -02:00
" Associated to '%s' ( " MAC_FMT " ) \n " ,
2007-05-25 17:09:41 -04:00
libertas_escape_essid ( adapter - > curbssparams . ssid . ssid ,
adapter - > curbssparams . ssid . ssidlength ) ,
MAC_ARG ( adapter - > curbssparams . bssid ) ) ;
2007-02-10 12:25:27 -02:00
libertas_prepare_and_send_command ( priv ,
cmd_802_11_rssi ,
0 , cmd_option_waitforrsp , 0 , NULL ) ;
libertas_prepare_and_send_command ( priv ,
cmd_802_11_get_log ,
0 , cmd_option_waitforrsp , 0 , NULL ) ;
} else {
ret = - 1 ;
}
}
out :
if ( ret ) {
2007-05-25 11:27:16 -04:00
lbs_deb_assoc ( " ASSOC: reconfiguration attempt unsuccessful: %d \n " ,
2007-02-10 12:25:27 -02:00
ret ) ;
}
2007-05-25 17:09:41 -04:00
mutex_lock ( & adapter - > lock ) ;
adapter - > in_progress_assoc_req = NULL ;
mutex_unlock ( & adapter - > lock ) ;
2007-02-10 12:25:27 -02:00
kfree ( assoc_req ) ;
2007-05-25 11:27:16 -04:00
done :
lbs_deb_leave ( LBS_DEB_ASSOC ) ;
2007-02-10 12:25:27 -02:00
}
/*
* Caller MUST hold any necessary locks
*/
struct assoc_request * wlan_get_association_request ( wlan_adapter * adapter )
{
struct assoc_request * assoc_req ;
2007-05-25 17:09:41 -04:00
if ( ! adapter - > pending_assoc_req ) {
adapter - > pending_assoc_req = kzalloc ( sizeof ( struct assoc_request ) ,
GFP_KERNEL ) ;
if ( ! adapter - > pending_assoc_req ) {
2007-02-10 12:25:27 -02:00
lbs_pr_info ( " Not enough memory to allocate association "
" request! \n " ) ;
return NULL ;
}
}
/* Copy current configuration attributes to the association request,
* but don ' t overwrite any that are already set .
*/
2007-05-25 17:09:41 -04:00
assoc_req = adapter - > pending_assoc_req ;
2007-02-10 12:25:27 -02:00
if ( ! test_bit ( ASSOC_FLAG_SSID , & assoc_req - > flags ) ) {
2007-05-25 17:09:41 -04:00
memcpy ( & assoc_req - > ssid , & adapter - > curbssparams . ssid ,
sizeof ( struct WLAN_802_11_SSID ) ) ;
2007-02-10 12:25:27 -02:00
}
if ( ! test_bit ( ASSOC_FLAG_CHANNEL , & assoc_req - > flags ) )
assoc_req - > channel = adapter - > curbssparams . channel ;
2007-05-25 17:09:41 -04:00
if ( ! test_bit ( ASSOC_FLAG_BAND , & assoc_req - > flags ) )
assoc_req - > band = adapter - > curbssparams . band ;
2007-02-10 12:25:27 -02:00
if ( ! test_bit ( ASSOC_FLAG_MODE , & assoc_req - > flags ) )
2007-05-10 22:58:02 -04:00
assoc_req - > mode = adapter - > mode ;
2007-02-10 12:25:27 -02:00
if ( ! test_bit ( ASSOC_FLAG_BSSID , & assoc_req - > flags ) ) {
memcpy ( & assoc_req - > bssid , adapter - > curbssparams . bssid ,
ETH_ALEN ) ;
}
if ( ! test_bit ( ASSOC_FLAG_WEP_KEYS , & assoc_req - > flags ) ) {
int i ;
for ( i = 0 ; i < 4 ; i + + ) {
memcpy ( & assoc_req - > wep_keys [ i ] , & adapter - > wep_keys [ i ] ,
sizeof ( struct WLAN_802_11_KEY ) ) ;
}
}
if ( ! test_bit ( ASSOC_FLAG_WEP_TX_KEYIDX , & assoc_req - > flags ) )
assoc_req - > wep_tx_keyidx = adapter - > wep_tx_keyidx ;
if ( ! test_bit ( ASSOC_FLAG_WPA_MCAST_KEY , & assoc_req - > flags ) ) {
memcpy ( & assoc_req - > wpa_mcast_key , & adapter - > wpa_mcast_key ,
sizeof ( struct WLAN_802_11_KEY ) ) ;
}
if ( ! test_bit ( ASSOC_FLAG_WPA_UCAST_KEY , & assoc_req - > flags ) ) {
memcpy ( & assoc_req - > wpa_unicast_key , & adapter - > wpa_unicast_key ,
sizeof ( struct WLAN_802_11_KEY ) ) ;
}
if ( ! test_bit ( ASSOC_FLAG_SECINFO , & assoc_req - > flags ) ) {
memcpy ( & assoc_req - > secinfo , & adapter - > secinfo ,
sizeof ( struct wlan_802_11_security ) ) ;
}
if ( ! test_bit ( ASSOC_FLAG_WPA_IE , & assoc_req - > flags ) ) {
memcpy ( & assoc_req - > wpa_ie , & adapter - > wpa_ie ,
MAX_WPA_IE_LEN ) ;
assoc_req - > wpa_ie_len = adapter - > wpa_ie_len ;
}
2007-05-25 17:09:41 -04:00
print_assoc_req ( __func__ , assoc_req ) ;
2007-02-10 12:25:27 -02:00
return assoc_req ;
}