summaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/core.c22
-rw-r--r--net/wireless/core.h5
-rw-r--r--net/wireless/mesh.c24
-rw-r--r--net/wireless/nl80211.c63
4 files changed, 90 insertions, 24 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 79772fcc37bc..e9a5f8ca4c27 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -789,13 +789,23 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
cfg80211_mgd_wext_connect(rdev, wdev);
break;
#endif
+#ifdef CONFIG_MAC80211_MESH
case NL80211_IFTYPE_MESH_POINT:
- /* backward compat code ... */
- if (wdev->mesh_id_up_len)
- __cfg80211_join_mesh(rdev, dev, wdev->ssid,
- wdev->mesh_id_up_len,
- &default_mesh_config);
- break;
+ {
+ /* backward compat code... */
+ struct mesh_setup setup;
+ memcpy(&setup, &default_mesh_setup,
+ sizeof(setup));
+ /* back compat only needed for mesh_id */
+ setup.mesh_id = wdev->ssid;
+ setup.mesh_id_len = wdev->mesh_id_up_len;
+ if (wdev->mesh_id_up_len)
+ __cfg80211_join_mesh(rdev, dev,
+ &setup,
+ &default_mesh_config);
+ break;
+ }
+#endif
default:
break;
}
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 743203bb61ac..26a0a084e16b 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -287,13 +287,14 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
/* mesh */
extern const struct mesh_config default_mesh_config;
+extern const struct mesh_setup default_mesh_setup;
int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
struct net_device *dev,
- const u8 *mesh_id, u8 mesh_id_len,
+ const struct mesh_setup *setup,
const struct mesh_config *conf);
int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
struct net_device *dev,
- const u8 *mesh_id, u8 mesh_id_len,
+ const struct mesh_setup *setup,
const struct mesh_config *conf);
int cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
struct net_device *dev);
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index e0b9747fe50a..73e39c171ffb 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -50,17 +50,19 @@ const struct mesh_config default_mesh_config = {
.min_discovery_timeout = MESH_MIN_DISCOVERY_TIMEOUT,
};
+const struct mesh_setup default_mesh_setup = {
+ .path_sel_proto = IEEE80211_PATH_PROTOCOL_HWMP,
+ .path_metric = IEEE80211_PATH_METRIC_AIRTIME,
+ .vendor_ie = NULL,
+ .vendor_ie_len = 0,
+};
int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
struct net_device *dev,
- const u8 *mesh_id, u8 mesh_id_len,
+ const struct mesh_setup *setup,
const struct mesh_config *conf)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
- struct mesh_setup setup = {
- .mesh_id = mesh_id,
- .mesh_id_len = mesh_id_len,
- };
int err;
BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != IEEE80211_MAX_MESH_ID_LEN);
@@ -73,16 +75,16 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
if (wdev->mesh_id_len)
return -EALREADY;
- if (!mesh_id_len)
+ if (!setup->mesh_id_len)
return -EINVAL;
if (!rdev->ops->join_mesh)
return -EOPNOTSUPP;
- err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, &setup);
+ err = rdev->ops->join_mesh(&rdev->wiphy, dev, conf, setup);
if (!err) {
- memcpy(wdev->ssid, mesh_id, mesh_id_len);
- wdev->mesh_id_len = mesh_id_len;
+ memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
+ wdev->mesh_id_len = setup->mesh_id_len;
}
return err;
@@ -90,14 +92,14 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
struct net_device *dev,
- const u8 *mesh_id, u8 mesh_id_len,
+ const struct mesh_setup *setup,
const struct mesh_config *conf)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
wdev_lock(wdev);
- err = __cfg80211_join_mesh(rdev, dev, mesh_id, mesh_id_len, conf);
+ err = __cfg80211_join_mesh(rdev, dev, setup, conf);
wdev_unlock(wdev);
return err;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 10be9350752e..eef89d0b558b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2773,6 +2773,14 @@ static const struct nla_policy nl80211_meshconf_params_policy[NL80211_MESHCONF_A
[NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME] = { .type = NLA_U16 },
};
+static const struct nla_policy
+ nl80211_mesh_setup_params_policy[NL80211_MESH_SETUP_ATTR_MAX+1] = {
+ [NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL] = { .type = NLA_U8 },
+ [NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC] = { .type = NLA_U8 },
+ [NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE] = { .type = NLA_BINARY,
+ .len = IEEE80211_MAX_DATA_LEN },
+};
+
static int nl80211_parse_mesh_config(struct genl_info *info,
struct mesh_config *cfg,
u32 *mask_out)
@@ -2839,14 +2847,50 @@ do {\
dot11MeshHWMPRootMode, mask,
NL80211_MESHCONF_HWMP_ROOTMODE,
nla_get_u8);
-
if (mask_out)
*mask_out = mask;
+
return 0;
#undef FILL_IN_MESH_PARAM_IF_SET
}
+static int nl80211_parse_mesh_setup(struct genl_info *info,
+ struct mesh_setup *setup)
+{
+ struct nlattr *tb[NL80211_MESH_SETUP_ATTR_MAX + 1];
+
+ if (!info->attrs[NL80211_ATTR_MESH_SETUP])
+ return -EINVAL;
+ if (nla_parse_nested(tb, NL80211_MESH_SETUP_ATTR_MAX,
+ info->attrs[NL80211_ATTR_MESH_SETUP],
+ nl80211_mesh_setup_params_policy))
+ return -EINVAL;
+
+ if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])
+ setup->path_sel_proto =
+ (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL])) ?
+ IEEE80211_PATH_PROTOCOL_VENDOR :
+ IEEE80211_PATH_PROTOCOL_HWMP;
+
+ if (tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])
+ setup->path_metric =
+ (nla_get_u8(tb[NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC])) ?
+ IEEE80211_PATH_METRIC_VENDOR :
+ IEEE80211_PATH_METRIC_AIRTIME;
+
+ if (tb[NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE]) {
+ struct nlattr *ieattr =
+ tb[NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE];
+ if (!is_valid_ie_attr(ieattr))
+ return -EINVAL;
+ setup->vendor_ie = nla_data(ieattr);
+ setup->vendor_ie_len = nla_len(ieattr);
+ }
+
+ return 0;
+}
+
static int nl80211_update_mesh_config(struct sk_buff *skb,
struct genl_info *info)
{
@@ -4667,10 +4711,12 @@ static int nl80211_join_mesh(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 mesh_config cfg;
+ struct mesh_setup setup;
int err;
/* start with default */
memcpy(&cfg, &default_mesh_config, sizeof(cfg));
+ memcpy(&setup, &default_mesh_setup, sizeof(setup));
if (info->attrs[NL80211_ATTR_MESH_CONFIG]) {
/* and parse parameters if given */
@@ -4683,10 +4729,17 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
!nla_len(info->attrs[NL80211_ATTR_MESH_ID]))
return -EINVAL;
- return cfg80211_join_mesh(rdev, dev,
- nla_data(info->attrs[NL80211_ATTR_MESH_ID]),
- nla_len(info->attrs[NL80211_ATTR_MESH_ID]),
- &cfg);
+ setup.mesh_id = nla_data(info->attrs[NL80211_ATTR_MESH_ID]);
+ setup.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]);
+
+ if (info->attrs[NL80211_ATTR_MESH_SETUP]) {
+ /* parse additional setup parameters if given */
+ err = nl80211_parse_mesh_setup(info, &setup);
+ if (err)
+ return err;
+ }
+
+ return cfg80211_join_mesh(rdev, dev, &setup, &cfg);
}
static int nl80211_leave_mesh(struct sk_buff *skb, struct genl_info *info)