@ -375,6 +375,9 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
[ NL80211_ATTR_VHT_CAPABILITY_MASK ] = {
. len = NL80211_VHT_CAPABILITY_LEN ,
} ,
[ NL80211_ATTR_MDID ] = { . type = NLA_U16 } ,
[ NL80211_ATTR_IE_RIC ] = { . type = NLA_BINARY ,
. len = IEEE80211_MAX_DATA_LEN } ,
} ;
/* policy for the key attributes */
@ -8160,6 +8163,27 @@ static int nl80211_get_protocol_features(struct sk_buff *skb,
return - ENOBUFS ;
}
static int nl80211_update_ft_ies ( struct sk_buff * skb , struct genl_info * info )
{
struct cfg80211_registered_device * rdev = info - > user_ptr [ 0 ] ;
struct cfg80211_update_ft_ies_params ft_params ;
struct net_device * dev = info - > user_ptr [ 1 ] ;
if ( ! rdev - > ops - > update_ft_ies )
return - EOPNOTSUPP ;
if ( ! info - > attrs [ NL80211_ATTR_MDID ] | |
! is_valid_ie_attr ( info - > attrs [ NL80211_ATTR_IE ] ) )
return - EINVAL ;
memset ( & ft_params , 0 , sizeof ( ft_params ) ) ;
ft_params . md = nla_get_u16 ( info - > attrs [ NL80211_ATTR_MDID ] ) ;
ft_params . ie = nla_data ( info - > attrs [ NL80211_ATTR_IE ] ) ;
ft_params . ie_len = nla_len ( info - > attrs [ NL80211_ATTR_IE ] ) ;
return rdev_update_ft_ies ( rdev , dev , & ft_params ) ;
}
# define NL80211_FLAG_NEED_WIPHY 0x01
# define NL80211_FLAG_NEED_NETDEV 0x02
# define NL80211_FLAG_NEED_RTNL 0x04
@ -8841,6 +8865,14 @@ static struct genl_ops nl80211_ops[] = {
. doit = nl80211_get_protocol_features ,
. policy = nl80211_policy ,
} ,
{
. cmd = NL80211_CMD_UPDATE_FT_IES ,
. doit = nl80211_update_ft_ies ,
. policy = nl80211_policy ,
. flags = GENL_ADMIN_PERM ,
. internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL ,
} ,
} ;
static struct genl_multicast_group nl80211_mlme_mcgrp = {
@ -10542,6 +10574,50 @@ static struct notifier_block nl80211_netlink_notifier = {
. notifier_call = nl80211_netlink_notify ,
} ;
void cfg80211_ft_event ( struct net_device * netdev ,
struct cfg80211_ft_event_params * ft_event )
{
struct wiphy * wiphy = netdev - > ieee80211_ptr - > wiphy ;
struct cfg80211_registered_device * rdev = wiphy_to_dev ( wiphy ) ;
struct sk_buff * msg ;
void * hdr ;
int err ;
trace_cfg80211_ft_event ( wiphy , netdev , ft_event ) ;
if ( ! ft_event - > target_ap )
return ;
msg = nlmsg_new ( NLMSG_DEFAULT_SIZE , GFP_KERNEL ) ;
if ( ! msg )
return ;
hdr = nl80211hdr_put ( msg , 0 , 0 , 0 , NL80211_CMD_FT_EVENT ) ;
if ( ! hdr ) {
nlmsg_free ( msg ) ;
return ;
}
nla_put_u32 ( msg , NL80211_ATTR_WIPHY , rdev - > wiphy_idx ) ;
nla_put_u32 ( msg , NL80211_ATTR_IFINDEX , netdev - > ifindex ) ;
nla_put ( msg , NL80211_ATTR_MAC , ETH_ALEN , ft_event - > target_ap ) ;
if ( ft_event - > ies )
nla_put ( msg , NL80211_ATTR_IE , ft_event - > ies_len , ft_event - > ies ) ;
if ( ft_event - > ric_ies )
nla_put ( msg , NL80211_ATTR_IE_RIC , ft_event - > ric_ies_len ,
ft_event - > ric_ies ) ;
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_KERNEL ) ;
}
EXPORT_SYMBOL ( cfg80211_ft_event ) ;
/* initialisation/exit functions */
int nl80211_init ( void )