@ -438,6 +438,52 @@ int send_and_recv_msgs(struct wpa_driver_nl80211_data *drv,
}
/* Use this method to mark that it is necessary to own the connection/interface
* for this operation .
* handle may be set to NULL , to get the same behavior as send_and_recv_msgs ( ) .
* set_owner can be used to mark this socket for receiving control port frames .
*/
static int send_and_recv_msgs_owner ( struct wpa_driver_nl80211_data * drv ,
struct nl_msg * msg ,
struct nl_sock * handle , int set_owner ,
int ( * valid_handler ) ( struct nl_msg * ,
void * ) ,
void * valid_data )
{
/* Control port over nl80211 needs the flags and attributes below.
*
* The Linux kernel has initial checks for them ( in nl80211 . c ) like :
* validate_pae_over_nl80211 ( . . . )
* or final checks like :
* dev - > ieee80211_ptr - > conn_owner_nlportid ! = info - > snd_portid
*
* Final operations ( e . g . , disassociate ) don ' t need to set these
* attributes , but they have to be performed on the socket , which has
* the connection owner property set in the kernel .
*/
if ( ( drv - > capa . flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX ) & &
handle & & set_owner & &
( nla_put_flag ( msg , NL80211_ATTR_CONTROL_PORT_OVER_NL80211 ) | |
nla_put_flag ( msg , NL80211_ATTR_SOCKET_OWNER ) | |
nla_put_u16 ( msg , NL80211_ATTR_CONTROL_PORT_ETHERTYPE , ETH_P_PAE ) | |
nla_put_flag ( msg , NL80211_ATTR_CONTROL_PORT_NO_PREAUTH ) ) )
return - 1 ;
return send_and_recv ( drv - > global , handle ? handle : drv - > global - > nl ,
msg , valid_handler , valid_data ) ;
}
struct nl_sock * get_connect_handle ( struct i802_bss * bss )
{
if ( ( bss - > drv - > capa . flags2 & WPA_DRIVER_FLAGS2_CONTROL_PORT_RX ) | |
bss - > use_nl_connect )
return bss - > nl_connect ;
return NULL ;
}
struct family_data {
const char * group ;
int id ;
@ -3437,18 +3483,14 @@ static int wpa_driver_nl80211_deauthenticate(struct i802_bss *bss,
return nl80211_leave_ibss ( drv , 1 ) ;
}
if ( ! ( drv - > capa . flags & WPA_DRIVER_FLAGS_SME ) ) {
struct nl_sock * nl_connect = NULL ;
if ( bss - > use_nl_connect )
nl_connect = bss - > nl_connect ;
return wpa_driver_nl80211_disconnect ( drv , reason_code ,
nl_connect ) ;
get_connect_handle ( bss ) ) ;
}
wpa_printf ( MSG_DEBUG , " %s(addr= " MACSTR " reason_code=%d) " ,
__func__ , MAC2STR ( addr ) , reason_code ) ;
nl80211_mark_disconnected ( drv ) ;
ret = wpa_driver_nl80211_mlme ( drv , addr , NL80211_CMD_DEAUTHENTICATE ,
reason_code , 0 , NULL ) ;
reason_code , 0 , get_connect_handle ( bss ) ) ;
/*
* For locally generated deauthenticate , supplicant already generates a
* DEAUTH event , so ignore the event from NL80211 .
@ -4432,7 +4474,8 @@ static int wpa_driver_nl80211_set_ap(void *priv,
}
# endif /* CONFIG_IEEE80211AX */
ret = send_and_recv_msgs ( drv , msg , NULL , NULL ) ;
ret = send_and_recv_msgs_owner ( drv , msg , get_connect_handle ( bss ) , 1 ,
NULL , NULL ) ;
if ( ret ) {
wpa_printf ( MSG_DEBUG , " nl80211: Beacon set failed: %d (%s) " ,
ret , strerror ( - ret ) ) ;
@ -5452,7 +5495,9 @@ static int nl80211_leave_ibss(struct wpa_driver_nl80211_data *drv,
int ret ;
msg = nl80211_drv_msg ( drv , 0 , NL80211_CMD_LEAVE_IBSS ) ;
ret = send_and_recv_msgs ( drv , msg , NULL , NULL ) ;
ret = send_and_recv_msgs_owner ( drv , msg ,
get_connect_handle ( drv - > first_bss ) , 1 ,
NULL , NULL ) ;
if ( ret ) {
wpa_printf ( MSG_DEBUG , " nl80211: Leave IBSS failed: ret=%d "
" (%s) " , ret , strerror ( - ret ) ) ;
@ -5584,7 +5629,9 @@ retry:
if ( ret < 0 )
goto fail ;
ret = send_and_recv_msgs ( drv , msg , NULL , NULL ) ;
ret = send_and_recv_msgs_owner ( drv , msg ,
get_connect_handle ( drv - > first_bss ) , 1 ,
NULL , NULL ) ;
msg = NULL ;
if ( ret ) {
wpa_printf ( MSG_DEBUG , " nl80211: Join IBSS failed: ret=%d (%s) " ,
@ -5985,12 +6032,8 @@ skip_auth_type:
if ( ret )
goto fail ;
if ( nl_connect )
ret = send_and_recv ( drv - > global , nl_connect , msg ,
NULL , ( void * ) - 1 ) ;
else
ret = send_and_recv_msgs ( drv , msg , NULL , ( void * ) - 1 ) ;
ret = send_and_recv_msgs_owner ( drv , msg , nl_connect , 1 , NULL ,
( void * ) - 1 ) ;
msg = NULL ;
if ( ret ) {
wpa_printf ( MSG_DEBUG , " nl80211: MLME connect failed: ret=%d "
@ -6059,19 +6102,17 @@ static int wpa_driver_nl80211_associate(
if ( ! ( drv - > capa . flags & WPA_DRIVER_FLAGS_SME ) ) {
enum nl80211_iftype nlmode = params - > p2p ?
NL80211_IFTYPE_P2P_CLIENT : NL80211_IFTYPE_STATION ;
struct nl_sock * nl_connect = NULL ;
if ( wpa_driver_nl80211_set_mode ( priv , nlmode ) < 0 )
return - 1 ;
if ( params - > key_mgmt_suite = = WPA_KEY_MGMT_SAE | |
params - > key_mgmt_suite = = WPA_KEY_MGMT_FT_SAE ) {
nl_connect = bss - > nl_connect ;
params - > key_mgmt_suite = = WPA_KEY_MGMT_FT_SAE )
bss - > use_nl_connect = 1 ;
} else {
else
bss - > use_nl_connect = 0 ;
}
return wpa_driver_nl80211_connect ( drv , params , nl_connect ) ;
return wpa_driver_nl80211_connect ( drv , params ,
get_connect_handle ( bss ) ) ;
}
nl80211_mark_disconnected ( drv ) ;
@ -6106,7 +6147,9 @@ static int wpa_driver_nl80211_associate(
goto fail ;
}
ret = send_and_recv_msgs ( drv , msg , NULL , NULL ) ;
ret = send_and_recv_msgs_owner ( drv , msg ,
get_connect_handle ( drv - > first_bss ) , 1 ,
NULL , NULL ) ;
msg = NULL ;
if ( ret ) {
wpa_dbg ( drv - > ctx , MSG_DEBUG ,
@ -9502,7 +9545,12 @@ static int nl80211_vendor_cmd(void *priv, unsigned int vendor_id,
if ( nlmsg_append ( msg , ( void * ) data , data_len , NLMSG_ALIGNTO ) <
0 )
goto fail ;
ret = send_and_recv_msgs ( drv , msg , cmd_reply_handler , buf ) ;
/* This test vendor_cmd can be used with nl80211 commands that
* need the connect nl_sock , so use the owner - setting variant
* of send_and_recv_msgs ( ) . */
ret = send_and_recv_msgs_owner ( drv , msg ,
get_connect_handle ( bss ) , 0 ,
cmd_reply_handler , buf ) ;
if ( ret )
wpa_printf ( MSG_DEBUG , " nl80211: command failed err=%d " ,
ret ) ;
@ -9957,7 +10005,8 @@ static int nl80211_join_mesh(struct i802_bss *bss,
if ( nl80211_put_mesh_config ( msg , & params - > conf ) < 0 )
goto fail ;
ret = send_and_recv_msgs ( drv , msg , NULL , NULL ) ;
ret = send_and_recv_msgs_owner ( drv , msg , get_connect_handle ( bss ) , 1 ,
NULL , NULL ) ;
msg = NULL ;
if ( ret ) {
wpa_printf ( MSG_DEBUG , " nl80211: mesh join failed: ret=%d (%s) " ,
@ -10014,7 +10063,8 @@ static int wpa_driver_nl80211_leave_mesh(void *priv)
wpa_printf ( MSG_DEBUG , " nl80211: mesh leave (ifindex=%d) " , drv - > ifindex ) ;
msg = nl80211_drv_msg ( drv , 0 , NL80211_CMD_LEAVE_MESH ) ;
ret = send_and_recv_msgs ( drv , msg , NULL , NULL ) ;
ret = send_and_recv_msgs_owner ( drv , msg , get_connect_handle ( bss ) , 0 ,
NULL , NULL ) ;
if ( ret ) {
wpa_printf ( MSG_DEBUG , " nl80211: mesh leave failed: ret=%d (%s) " ,
ret , strerror ( - ret ) ) ;