nl80211: New notification to discover mesh peer candidates.
authorJavier Cardona <javier@cozybit.com>
Thu, 7 Apr 2011 22:08:34 +0000 (15:08 -0700)
committerJohn W. Linville <linville@tuxdriver.com>
Tue, 12 Apr 2011 20:57:39 +0000 (16:57 -0400)
Notify userspace when a beacon/presp is received from a suitable mesh
peer candidate for whom no sta information exists.  Userspace can then
decide to create a sta info for the candidate.  If userspace is not
ready to authenticate the peer right away, it can create the sta info
with the authenticated flag unset and set it later.

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/wireless/mesh.c
net/wireless/nl80211.c
net/wireless/nl80211.h

index 5ec4ac3a0ef40a00c250547c001359ea91ddbda1..b87481866ddeec0293743503b8d66adaa2734c52 100644 (file)
  *     notification. This event is used to indicate that an unprotected
  *     disassociation frame was dropped when MFP is in use.
  *
+ * @NL80211_CMD_NEW_PEER_CANDIDATE: Notification on the reception of a
+ *      beacon or probe response from a compatible mesh peer.  This is only
+ *      sent while no station information (sta_info) exists for the new peer
+ *      candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH is set.  On
+ *      reception of this notification, userspace may decide to create a new
+ *      station (@NL80211_CMD_NEW_STATION).  To stop this notification from
+ *      reoccurring, the userspace authentication daemon may want to create the
+ *      new station with the AUTHENTICATED flag unset and maybe change it later
+ *      depending on the authentication result.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -522,6 +532,8 @@ enum nl80211_commands {
        NL80211_CMD_UNPROT_DEAUTHENTICATE,
        NL80211_CMD_UNPROT_DISASSOCIATE,
 
+       NL80211_CMD_NEW_PEER_CANDIDATE,
+
        /* add new commands above here */
 
        /* used to define NL80211_CMD_MAX below */
index e77603bd1630be4725e9a78384ae4a1b1c2100ce..f40cd30847ded6bf33b6f501fce6088e3eae2d6e 100644 (file)
@@ -2488,6 +2488,22 @@ void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
  */
 void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp);
 
+/**
+ * cfg80211_notify_new_candidate - notify cfg80211 of a new mesh peer candidate
+ *
+ * @dev: network device
+ * @macaddr: the MAC address of the new candidate
+ * @ie: information elements advertised by the peer candidate
+ * @ie_len: lenght of the information elements buffer
+ * @gfp: allocation flags
+ *
+ * This function notifies cfg80211 that the mesh peer candidate has been
+ * detected, most likely via a beacon or, less likely, via a probe response.
+ * cfg80211 then sends a notification to userspace.
+ */
+void cfg80211_notify_new_peer_candidate(struct net_device *dev,
+               const u8 *macaddr, const u8 *ie, u8 ie_len, gfp_t gfp);
+
 /**
  * DOC: RFkill integration
  *
index e0226e8265a3f2995c7f529fe7e2b8e897d235ad..5c116083eeca7f99c28b9f8e9835a5d32e0e24db 100644 (file)
@@ -1,5 +1,6 @@
 #include <linux/ieee80211.h>
 #include <net/cfg80211.h>
+#include "nl80211.h"
 #include "core.h"
 
 /* Default values, timeouts in ms */
@@ -110,6 +111,19 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
        return err;
 }
 
+void cfg80211_notify_new_peer_candidate(struct net_device *dev,
+               const u8 *macaddr, const u8* ie, u8 ie_len, gfp_t gfp)
+{
+       struct wireless_dev *wdev = dev->ieee80211_ptr;
+
+       if (WARN_ON(wdev->iftype != NL80211_IFTYPE_MESH_POINT))
+               return;
+
+       nl80211_send_new_peer_candidate(wiphy_to_dev(wdev->wiphy), dev,
+                       macaddr, ie, ie_len, gfp);
+}
+EXPORT_SYMBOL(cfg80211_notify_new_peer_candidate);
+
 static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev,
                                 struct net_device *dev)
 {
index f4cb8efe2e5f9d67411ec3c5b4fa52fa2f61a811..58f501a3502275d5bb1cf9ba1e9080fddb4bcfa8 100644 (file)
@@ -5818,6 +5818,44 @@ void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
        nlmsg_free(msg);
 }
 
+void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev,
+               struct net_device *netdev,
+               const u8 *macaddr, const u8* ie, u8 ie_len,
+               gfp_t gfp)
+{
+       struct sk_buff *msg;
+       void *hdr;
+
+       msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+       if (!msg)
+               return;
+
+       hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_NEW_PEER_CANDIDATE);
+       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, macaddr);
+       if (ie_len && ie)
+               NLA_PUT(msg, NL80211_ATTR_IE, ie_len , ie);
+
+       if (genlmsg_end(msg, hdr) < 0) {
+               nlmsg_free(msg);
+               return;
+       }
+
+       genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
+                               nl80211_mlme_mcgrp.id, gfp);
+       return;
+
+ nla_put_failure:
+       genlmsg_cancel(msg, hdr);
+       nlmsg_free(msg);
+}
+
 void nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
                                 struct net_device *netdev, const u8 *addr,
                                 enum nl80211_key_type key_type, int key_id,
index dcac5cd6f0178694f70dbfc93558c5ccb43ef447..f2af6955a665654f498a29ce504574f999495763 100644 (file)
@@ -50,6 +50,10 @@ void nl80211_send_disconnected(struct cfg80211_registered_device *rdev,
                               struct net_device *netdev, u16 reason,
                               const u8 *ie, size_t ie_len, bool from_ap);
 
+void nl80211_send_new_peer_candidate(struct cfg80211_registered_device *rdev,
+                                    struct net_device *netdev,
+                                    const u8 *macaddr, const u8* ie, u8 ie_len,
+                                    gfp_t gfp);
 void
 nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
                            struct net_device *netdev, const u8 *addr,