@ -890,6 +890,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
}
if ( dev - > wiphy . flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN )
CMD ( sched_scan_start , START_SCHED_SCAN ) ;
CMD ( probe_client , PROBE_CLIENT ) ;
# undef CMD
@ -5853,6 +5854,59 @@ static int nl80211_register_unexpected_frame(struct sk_buff *skb,
return 0 ;
}
static int nl80211_probe_client ( struct sk_buff * skb ,
struct genl_info * info )
{
struct cfg80211_registered_device * rdev = info - > user_ptr [ 0 ] ;
struct net_device * dev = info - > user_ptr [ 1 ] ;
struct wireless_dev * wdev = dev - > ieee80211_ptr ;
struct sk_buff * msg ;
void * hdr ;
const u8 * addr ;
u64 cookie ;
int err ;
if ( wdev - > iftype ! = NL80211_IFTYPE_AP & &
wdev - > iftype ! = NL80211_IFTYPE_P2P_GO )
return - EOPNOTSUPP ;
if ( ! info - > attrs [ NL80211_ATTR_MAC ] )
return - EINVAL ;
if ( ! rdev - > ops - > probe_client )
return - EOPNOTSUPP ;
msg = nlmsg_new ( NLMSG_DEFAULT_SIZE , GFP_KERNEL ) ;
if ( ! msg )
return - ENOMEM ;
hdr = nl80211hdr_put ( msg , info - > snd_pid , info - > snd_seq , 0 ,
NL80211_CMD_PROBE_CLIENT ) ;
if ( IS_ERR ( hdr ) ) {
err = PTR_ERR ( hdr ) ;
goto free_msg ;
}
addr = nla_data ( info - > attrs [ NL80211_ATTR_MAC ] ) ;
err = rdev - > ops - > probe_client ( & rdev - > wiphy , dev , addr , & cookie ) ;
if ( err )
goto free_msg ;
NLA_PUT_U64 ( msg , NL80211_ATTR_COOKIE , cookie ) ;
genlmsg_end ( msg , hdr ) ;
return genlmsg_reply ( msg , info ) ;
nla_put_failure :
err = - ENOBUFS ;
free_msg :
nlmsg_free ( msg ) ;
return err ;
}
# define NL80211_FLAG_NEED_WIPHY 0x01
# define NL80211_FLAG_NEED_NETDEV 0x02
# define NL80211_FLAG_NEED_RTNL 0x04
@ -6416,6 +6470,14 @@ static struct genl_ops nl80211_ops[] = {
. internal_flags = NL80211_FLAG_NEED_NETDEV |
NL80211_FLAG_NEED_RTNL ,
} ,
{
. cmd = NL80211_CMD_PROBE_CLIENT ,
. doit = nl80211_probe_client ,
. policy = nl80211_policy ,
. flags = GENL_ADMIN_PERM ,
. internal_flags = NL80211_FLAG_NEED_NETDEV |
NL80211_FLAG_NEED_RTNL ,
} ,
} ;
static struct genl_multicast_group nl80211_mlme_mcgrp = {
@ -7478,6 +7540,48 @@ nl80211_send_cqm_pktloss_notify(struct cfg80211_registered_device *rdev,
nlmsg_free ( msg ) ;
}
void cfg80211_probe_status ( struct net_device * dev , const u8 * addr ,
u64 cookie , bool acked , gfp_t gfp )
{
struct wireless_dev * wdev = dev - > ieee80211_ptr ;
struct cfg80211_registered_device * rdev = wiphy_to_dev ( wdev - > wiphy ) ;
struct sk_buff * msg ;
void * hdr ;
int err ;
msg = nlmsg_new ( NLMSG_GOODSIZE , gfp ) ;
if ( ! msg )
return ;
hdr = nl80211hdr_put ( msg , 0 , 0 , 0 , NL80211_CMD_PROBE_CLIENT ) ;
if ( ! hdr ) {
nlmsg_free ( msg ) ;
return ;
}
NLA_PUT_U32 ( msg , NL80211_ATTR_WIPHY , rdev - > wiphy_idx ) ;
NLA_PUT_U32 ( msg , NL80211_ATTR_IFINDEX , dev - > ifindex ) ;
NLA_PUT ( msg , NL80211_ATTR_MAC , ETH_ALEN , addr ) ;
NLA_PUT_U64 ( msg , NL80211_ATTR_COOKIE , cookie ) ;
if ( acked )
NLA_PUT_FLAG ( msg , NL80211_ATTR_ACK ) ;
err = genlmsg_end ( msg , hdr ) ;
if ( err < 0 ) {
nlmsg_free ( msg ) ;
return ;
}
genlmsg_multicast_netns ( wiphy_net ( & rdev - > wiphy ) , msg , 0 ,
nl80211_mlme_mcgrp . id , gfp ) ;
return ;
nla_put_failure :
genlmsg_cancel ( msg , hdr ) ;
nlmsg_free ( msg ) ;
}
EXPORT_SYMBOL ( cfg80211_probe_status ) ;
static int nl80211_netlink_notify ( struct notifier_block * nb ,
unsigned long state ,
void * _notify )