Commit b130e5ce authored by Javier Cardona's avatar Javier Cardona Committed by John W. Linville

nl80211: Introduce NL80211_MESH_SETUP_USERSPACE_AMPE

Introduce a new configuration option to support AMPE from userspace.

Prior to this series we only supported authentication in userspace: an
authentication daemon would authenticate peer candidates in userspace
and hand them over to the kernel.  From that point the mesh stack would
take over and establish a peer link (Mesh Peering Management).

These patches introduce support for Authenticated Mesh Peering Exchange
in userspace.  The userspace daemon implements the AMPE protocol and on
successfull completion create mesh peers and install encryption keys.
Signed-off-by: default avatarJavier Cardona <javier@cozybit.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent f3a57fd1
...@@ -1769,6 +1769,15 @@ enum nl80211_meshconf_params { ...@@ -1769,6 +1769,15 @@ enum nl80211_meshconf_params {
* @NL80211_MESH_SETUP_USERSPACE_AUTH: Enable this option if an authentication * @NL80211_MESH_SETUP_USERSPACE_AUTH: Enable this option if an authentication
* daemon will be authenticating mesh candidates. * daemon will be authenticating mesh candidates.
* *
* @NL80211_MESH_SETUP_USERSPACE_AMPE: Enable this option if an authentication
* daemon will be securing peer link frames. AMPE is a secured version of Mesh
* Peering Management (MPM) and is implemented with the assistance of a
* userspace daemon. When this flag is set, the kernel will send peer
* management frames to a userspace daemon that will implement AMPE
* functionality (security capabilities selection, key confirmation, and key
* management). When the flag is unset (default), the kernel can autonomously
* complete (unsecured) mesh peering without the need of a userspace daemon.
*
* @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number
* @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use
*/ */
...@@ -1778,6 +1787,7 @@ enum nl80211_mesh_setup_params { ...@@ -1778,6 +1787,7 @@ enum nl80211_mesh_setup_params {
NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC, NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC,
NL80211_MESH_SETUP_IE, NL80211_MESH_SETUP_IE,
NL80211_MESH_SETUP_USERSPACE_AUTH, NL80211_MESH_SETUP_USERSPACE_AUTH,
NL80211_MESH_SETUP_USERSPACE_AMPE,
/* keep last */ /* keep last */
__NL80211_MESH_SETUP_ATTR_AFTER_LAST, __NL80211_MESH_SETUP_ATTR_AFTER_LAST,
......
...@@ -695,7 +695,8 @@ struct mesh_config { ...@@ -695,7 +695,8 @@ struct mesh_config {
* @path_metric: which metric to use * @path_metric: which metric to use
* @ie: vendor information elements (optional) * @ie: vendor information elements (optional)
* @ie_len: length of vendor information elements * @ie_len: length of vendor information elements
* @is_secure: or not * @is_authenticated: this mesh requires authentication
* @is_secure: this mesh uses security
* *
* These parameters are fixed when the mesh is created. * These parameters are fixed when the mesh is created.
*/ */
...@@ -706,6 +707,7 @@ struct mesh_setup { ...@@ -706,6 +707,7 @@ struct mesh_setup {
u8 path_metric; u8 path_metric;
const u8 *ie; const u8 *ie;
u8 ie_len; u8 ie_len;
bool is_authenticated;
bool is_secure; bool is_secure;
}; };
......
...@@ -1064,7 +1064,11 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh, ...@@ -1064,7 +1064,11 @@ static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len); memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len);
ifmsh->mesh_pp_id = setup->path_sel_proto; ifmsh->mesh_pp_id = setup->path_sel_proto;
ifmsh->mesh_pm_id = setup->path_metric; ifmsh->mesh_pm_id = setup->path_metric;
ifmsh->is_secure = setup->is_secure; ifmsh->security = IEEE80211_MESH_SEC_NONE;
if (setup->is_authenticated)
ifmsh->security |= IEEE80211_MESH_SEC_AUTHED;
if (setup->is_secure)
ifmsh->security |= IEEE80211_MESH_SEC_SECURED;
return 0; return 0;
} }
......
...@@ -490,7 +490,11 @@ struct ieee80211_if_mesh { ...@@ -490,7 +490,11 @@ struct ieee80211_if_mesh {
bool accepting_plinks; bool accepting_plinks;
const u8 *ie; const u8 *ie;
u8 ie_len; u8 ie_len;
bool is_secure; enum {
IEEE80211_MESH_SEC_NONE = 0x0,
IEEE80211_MESH_SEC_AUTHED = 0x1,
IEEE80211_MESH_SEC_SECURED = 0x2,
} security;
}; };
#ifdef CONFIG_MAC80211_MESH #ifdef CONFIG_MAC80211_MESH
......
...@@ -574,7 +574,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, ...@@ -574,7 +574,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
&elems); &elems);
/* ignore beacons from secure mesh peers if our security is off */ /* ignore beacons from secure mesh peers if our security is off */
if (elems.rsn_len && !sdata->u.mesh.is_secure) if (elems.rsn_len && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE)
return; return;
if (elems.ds_params && elems.ds_params_len == 1) if (elems.ds_params && elems.ds_params_len == 1)
......
...@@ -251,7 +251,7 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates, ...@@ -251,7 +251,7 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates,
rcu_read_unlock(); rcu_read_unlock();
/* Userspace handles peer allocation when security is enabled /* Userspace handles peer allocation when security is enabled
* */ * */
if (sdata->u.mesh.is_secure) if (sdata->u.mesh.security & IEEE80211_MESH_SEC_AUTHED)
cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr, cfg80211_notify_new_peer_candidate(sdata->dev, hw_addr,
elems->ie_start, elems->total_len, elems->ie_start, elems->total_len,
GFP_KERNEL); GFP_KERNEL);
...@@ -460,7 +460,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m ...@@ -460,7 +460,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m
mpl_dbg("Mesh plink: missing necessary peer link ie\n"); mpl_dbg("Mesh plink: missing necessary peer link ie\n");
return; return;
} }
if (elems.rsn_len && !sdata->u.mesh.is_secure) { if (elems.rsn_len &&
sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) {
mpl_dbg("Mesh plink: can't establish link with secure peer\n"); mpl_dbg("Mesh plink: can't establish link with secure peer\n");
return; return;
} }
......
...@@ -2871,6 +2871,7 @@ static const struct nla_policy ...@@ -2871,6 +2871,7 @@ static const struct nla_policy
[NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG }, [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },
[NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY, [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY,
.len = IEEE80211_MAX_DATA_LEN }, .len = IEEE80211_MAX_DATA_LEN },
[NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
}; };
static int nl80211_parse_mesh_config(struct genl_info *info, static int nl80211_parse_mesh_config(struct genl_info *info,
...@@ -2980,7 +2981,8 @@ static int nl80211_parse_mesh_setup(struct genl_info *info, ...@@ -2980,7 +2981,8 @@ static int nl80211_parse_mesh_setup(struct genl_info *info,
setup->ie = nla_data(ieattr); setup->ie = nla_data(ieattr);
setup->ie_len = nla_len(ieattr); setup->ie_len = nla_len(ieattr);
} }
setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]); setup->is_authenticated = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AUTH]);
setup->is_secure = nla_get_flag(tb[NL80211_MESH_SETUP_USERSPACE_AMPE]);
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment