|
|
@@ -10919,6 +10919,40 @@ static int nl80211_nan_del_func(struct sk_buff *skb,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int nl80211_nan_change_config(struct sk_buff *skb,
|
|
|
+ struct genl_info *info)
|
|
|
+{
|
|
|
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
|
|
|
+ struct wireless_dev *wdev = info->user_ptr[1];
|
|
|
+ struct cfg80211_nan_conf conf = {};
|
|
|
+ u32 changed = 0;
|
|
|
+
|
|
|
+ if (wdev->iftype != NL80211_IFTYPE_NAN)
|
|
|
+ return -EOPNOTSUPP;
|
|
|
+
|
|
|
+ if (!wdev->nan_started)
|
|
|
+ return -ENOTCONN;
|
|
|
+
|
|
|
+ if (info->attrs[NL80211_ATTR_NAN_MASTER_PREF]) {
|
|
|
+ conf.master_pref =
|
|
|
+ nla_get_u8(info->attrs[NL80211_ATTR_NAN_MASTER_PREF]);
|
|
|
+ if (conf.master_pref <= 1 || conf.master_pref == 255)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ changed |= CFG80211_NAN_CONF_CHANGED_PREF;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (info->attrs[NL80211_ATTR_NAN_DUAL]) {
|
|
|
+ conf.dual = nla_get_u8(info->attrs[NL80211_ATTR_NAN_DUAL]);
|
|
|
+ changed |= CFG80211_NAN_CONF_CHANGED_DUAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!changed)
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ return rdev_nan_change_conf(rdev, wdev, &conf, changed);
|
|
|
+}
|
|
|
+
|
|
|
static int nl80211_get_protocol_features(struct sk_buff *skb,
|
|
|
struct genl_info *info)
|
|
|
{
|
|
|
@@ -12292,6 +12326,14 @@ static const struct genl_ops nl80211_ops[] = {
|
|
|
.internal_flags = NL80211_FLAG_NEED_WDEV_UP |
|
|
|
NL80211_FLAG_NEED_RTNL,
|
|
|
},
|
|
|
+ {
|
|
|
+ .cmd = NL80211_CMD_CHANGE_NAN_CONFIG,
|
|
|
+ .doit = nl80211_nan_change_config,
|
|
|
+ .policy = nl80211_policy,
|
|
|
+ .flags = GENL_ADMIN_PERM,
|
|
|
+ .internal_flags = NL80211_FLAG_NEED_WDEV_UP |
|
|
|
+ NL80211_FLAG_NEED_RTNL,
|
|
|
+ },
|
|
|
{
|
|
|
.cmd = NL80211_CMD_SET_MCAST_RATE,
|
|
|
.doit = nl80211_set_mcast_rate,
|