nl80211: Introduce NL80211_MESH_SETUP_USERSPACE_AMPE
authorJavier Cardona <javier@cozybit.com>
Tue, 3 May 2011 23:57:07 +0000 (16:57 -0700)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 11 May 2011 18:37:47 +0000 (14:37 -0400)
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: Javier Cardona <javier@cozybit.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
include/linux/nl80211.h
include/net/cfg80211.h
net/mac80211/cfg.c
net/mac80211/ieee80211_i.h
net/mac80211/mesh.c
net/mac80211/mesh_plink.c
net/wireless/nl80211.c

index a75dea9c416e40a4919994698b2e5a5383645982..c53b916036c5ff85aebe9539066cb3e97af60ccc 100644 (file)
@@ -1769,6 +1769,15 @@ enum nl80211_meshconf_params {
  * @NL80211_MESH_SETUP_USERSPACE_AUTH: Enable this option if an authentication
  * 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_AFTER_LAST: Internal use
  */
@@ -1778,6 +1787,7 @@ enum nl80211_mesh_setup_params {
        NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC,
        NL80211_MESH_SETUP_IE,
        NL80211_MESH_SETUP_USERSPACE_AUTH,
+       NL80211_MESH_SETUP_USERSPACE_AMPE,
 
        /* keep last */
        __NL80211_MESH_SETUP_ATTR_AFTER_LAST,
index 0920daf3680723569951adc36c7d889538a5a0ce..10c17d68059f1110c2b9b6201c2ddde858fc611b 100644 (file)
@@ -695,7 +695,8 @@ struct mesh_config {
  * @path_metric: which metric to use
  * @ie: vendor information elements (optional)
  * @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.
  */
@@ -706,6 +707,7 @@ struct mesh_setup {
        u8  path_metric;
        const u8 *ie;
        u8 ie_len;
+       bool is_authenticated;
        bool is_secure;
 };
 
index 1ebc13383ae790321b3c10e59ebd71314a0efccb..18c2555e04e64009d8076ec91073083d640937ce 100644 (file)
@@ -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);
        ifmsh->mesh_pp_id = setup->path_sel_proto;
        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;
 }
index e89bc27f8dc3432b85fce17ed96b03073f17b416..7f4d0dc1d534a47266239d84009bba502c5eba98 100644 (file)
@@ -490,7 +490,11 @@ struct ieee80211_if_mesh {
        bool accepting_plinks;
        const u8 *ie;
        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
index c1299e24954166cde73832d39becf830fb01ef29..2a59eb3451318429b3dce29054c232b486ee68a6 100644 (file)
@@ -574,7 +574,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
                               &elems);
 
        /* 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;
 
        if (elems.ds_params && elems.ds_params_len == 1)
index 84e5b056af022a33d3016ebc3b813c61a370ee22..87abf8deb369a52f7d513fe738a53a786d602a69 100644 (file)
@@ -251,7 +251,7 @@ void mesh_neighbour_update(u8 *hw_addr, u32 rates,
                rcu_read_unlock();
                /* 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,
                                        elems->ie_start, elems->total_len,
                                        GFP_KERNEL);
@@ -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");
                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");
                return;
        }
index 0a199a1ca9b694e539e747db7275009256886c3a..64efc2d7a7add2f03538709eb9d1be8f5f796e21 100644 (file)
@@ -2871,6 +2871,7 @@ static const struct nla_policy
        [NL80211_MESH_SETUP_USERSPACE_AUTH] = { .type = NLA_FLAG },
        [NL80211_MESH_SETUP_IE] = { .type = NLA_BINARY,
                .len = IEEE80211_MAX_DATA_LEN },
+       [NL80211_MESH_SETUP_USERSPACE_AMPE] = { .type = NLA_FLAG },
 };
 
 static int nl80211_parse_mesh_config(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_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;
 }