nl80211: Add event for authentication/association timeout
authorJouni Malinen <jouni.malinen@atheros.com>
Wed, 22 Apr 2009 18:38:25 +0000 (21:38 +0300)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 22 Apr 2009 20:57:21 +0000 (16:57 -0400)
SME needs to be notified when the authentication or association
attempt times out and MLME has stopped processing in order to allow
the SME to decide what to do next.

Signed-off-by: Jouni Malinen <jouni.malinen@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
include/linux/nl80211.h
include/net/cfg80211.h
net/mac80211/mlme.c
net/wireless/mlme.c
net/wireless/nl80211.c
net/wireless/nl80211.h

index b6a48dd502ce441880e6d54c807568d5492b380f..e9fd13aa79f0c485d63b94891d27faa84d59228e 100644 (file)
  *     frame, i.e., it was for the local STA and was received in correct
  *     state. This is similar to MLME-AUTHENTICATE.confirm primitive in the
  *     MLME SAP interface (kernel providing MLME, userspace SME). The
- *     included NL80211_ATTR_FRAME attribute contains the management frame
- *     (including both the header and frame body, but not FCS).
+ *     included %NL80211_ATTR_FRAME attribute contains the management frame
+ *     (including both the header and frame body, but not FCS). This event is
+ *     also used to indicate if the authentication attempt timed out. In that
+ *     case the %NL80211_ATTR_FRAME attribute is replaced with a
+ *     %NL80211_ATTR_TIMED_OUT flag (and %NL80211_ATTR_MAC to indicate which
+ *     pending authentication timed out).
  * @NL80211_CMD_ASSOCIATE: association request and notification; like
  *     NL80211_CMD_AUTHENTICATE but for Association and Reassociation
  *     (similar to MLME-ASSOCIATE.request, MLME-REASSOCIATE.request,
@@ -487,6 +491,9 @@ enum nl80211_commands {
  * @NL80211_ATTR_FREQ_FIXED: a flag indicating the IBSS should not try to look
  *     for other networks on different channels
  *
+ * @NL80211_ATTR_TIMED_OUT: a flag indicating than an operation timed out; this
+ *     is used, e.g., with %NL80211_CMD_AUTHENTICATE event
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -587,6 +594,8 @@ enum nl80211_attrs {
        NL80211_ATTR_WIPHY_FRAG_THRESHOLD,
        NL80211_ATTR_WIPHY_RTS_THRESHOLD,
 
+       NL80211_ATTR_TIMED_OUT,
+
        /* add attributes here, update the policy in nl80211.c */
 
        __NL80211_ATTR_AFTER_LAST,
index 7f7b53b69cb2cd0f88856fde093a379e457b9026..b8a76764e1c57aa3079eb962415766f042a137e3 100644 (file)
@@ -1475,10 +1475,19 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *bss);
  * @len: length of the frame data
  *
  * This function is called whenever an authentication has been processed in
- * station mode.
+ * station mode. The driver is required to call either this function or
+ * cfg80211_send_auth_timeout() to indicate the result of cfg80211_ops::auth()
+ * call.
  */
 void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
 
+/**
+ * cfg80211_send_auth_timeout - notification of timed out authentication
+ * @dev: network device
+ * @addr: The MAC address of the device with which the authentication timed out
+ */
+void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr);
+
 /**
  * cfg80211_send_rx_assoc - notification of processed association
  * @dev: network device
@@ -1486,10 +1495,19 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
  * @len: length of the frame data
  *
  * This function is called whenever a (re)association response has been
- * processed in station mode.
+ * processed in station mode. The driver is required to call either this
+ * function or cfg80211_send_assoc_timeout() to indicate the result of
+ * cfg80211_ops::assoc() call.
  */
 void cfg80211_send_rx_assoc(struct net_device *dev, const u8 *buf, size_t len);
 
+/**
+ * cfg80211_send_assoc_timeout - notification of timed out association
+ * @dev: network device
+ * @addr: The MAC address of the device with which the association timed out
+ */
+void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr);
+
 /**
  * cfg80211_send_deauth - notification of processed deauthentication
  * @dev: network device
index df27c68620c9462e506575c79c6072a971a6fcf4..3610c11286bc10ab230255581ce77ac550828449 100644 (file)
@@ -932,7 +932,7 @@ static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata)
                       " timed out\n",
                       sdata->dev->name, ifmgd->bssid);
                ifmgd->state = IEEE80211_STA_MLME_DISABLED;
-               ieee80211_sta_send_apinfo(sdata);
+               cfg80211_send_auth_timeout(sdata->dev, ifmgd->bssid);
                ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
                                sdata->local->hw.conf.channel->center_freq,
                                ifmgd->ssid, ifmgd->ssid_len);
@@ -1115,7 +1115,7 @@ static void ieee80211_associate(struct ieee80211_sub_if_data *sdata)
                       " timed out\n",
                       sdata->dev->name, ifmgd->bssid);
                ifmgd->state = IEEE80211_STA_MLME_DISABLED;
-               ieee80211_sta_send_apinfo(sdata);
+               cfg80211_send_assoc_timeout(sdata->dev, ifmgd->bssid);
                ieee80211_rx_bss_remove(sdata, ifmgd->bssid,
                                sdata->local->hw.conf.channel->center_freq,
                                ifmgd->ssid, ifmgd->ssid_len);
index 1407244a647ea7d8071adb85aca5aebec208cc0b..42184361a1099745dc17b0aedd8ebc6d2217bd97 100644 (file)
@@ -44,6 +44,33 @@ void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
 }
 EXPORT_SYMBOL(cfg80211_send_disassoc);
 
+static void cfg80211_wext_disconnected(struct net_device *dev)
+{
+#ifdef CONFIG_WIRELESS_EXT
+       union iwreq_data wrqu;
+       memset(&wrqu, 0, sizeof(wrqu));
+       wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+#endif
+}
+
+void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
+{
+       struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+       struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+       nl80211_send_auth_timeout(rdev, dev, addr);
+       cfg80211_wext_disconnected(dev);
+}
+EXPORT_SYMBOL(cfg80211_send_auth_timeout);
+
+void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr)
+{
+       struct wiphy *wiphy = dev->ieee80211_ptr->wiphy;
+       struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+       nl80211_send_assoc_timeout(rdev, dev, addr);
+       cfg80211_wext_disconnected(dev);
+}
+EXPORT_SYMBOL(cfg80211_send_assoc_timeout);
+
 void cfg80211_michael_mic_failure(struct net_device *dev, const u8 *addr,
                                  enum nl80211_key_type key_type, int key_id,
                                  const u8 *tsc)
index 3b21b3e89e9646d444949046f39de869e798ad92..b1fc98225fd1695af405ccdeb11434a317a84547 100644 (file)
@@ -121,6 +121,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
        [NL80211_ATTR_AUTH_TYPE] = { .type = NLA_U32 },
        [NL80211_ATTR_REASON_CODE] = { .type = NLA_U16 },
        [NL80211_ATTR_FREQ_FIXED] = { .type = NLA_FLAG },
+       [NL80211_ATTR_TIMED_OUT] = { .type = NLA_FLAG },
 };
 
 /* IE validation */
@@ -3695,6 +3696,54 @@ void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
                                NL80211_CMD_DISASSOCIATE);
 }
 
+void nl80211_send_mlme_timeout(struct cfg80211_registered_device *rdev,
+                              struct net_device *netdev, int cmd,
+                              const u8 *addr)
+{
+       struct sk_buff *msg;
+       void *hdr;
+
+       msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
+       if (!msg)
+               return;
+
+       hdr = nl80211hdr_put(msg, 0, 0, 0, cmd);
+       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_FLAG(msg, NL80211_ATTR_TIMED_OUT);
+       NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, addr);
+
+       if (genlmsg_end(msg, hdr) < 0) {
+               nlmsg_free(msg);
+               return;
+       }
+
+       genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_ATOMIC);
+       return;
+
+ nla_put_failure:
+       genlmsg_cancel(msg, hdr);
+       nlmsg_free(msg);
+}
+
+void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
+                              struct net_device *netdev, const u8 *addr)
+{
+       nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_AUTHENTICATE,
+                                 addr);
+}
+
+void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
+                               struct net_device *netdev, const u8 *addr)
+{
+       nl80211_send_mlme_timeout(rdev, netdev, NL80211_CMD_ASSOCIATE, addr);
+}
+
 void nl80211_send_ibss_bssid(struct cfg80211_registered_device *rdev,
                             struct net_device *netdev, const u8 *bssid,
                             gfp_t gfp)
index 17d2d8bfaf7589b1453bfc9b763ca0cd7c44acac..5c12ad13499b01d47ebb84f0f8ef570ba8ae6429 100644 (file)
@@ -23,6 +23,12 @@ extern void nl80211_send_deauth(struct cfg80211_registered_device *rdev,
 extern void nl80211_send_disassoc(struct cfg80211_registered_device *rdev,
                                  struct net_device *netdev,
                                  const u8 *buf, size_t len);
+extern void nl80211_send_auth_timeout(struct cfg80211_registered_device *rdev,
+                                     struct net_device *netdev,
+                                     const u8 *addr);
+extern void nl80211_send_assoc_timeout(struct cfg80211_registered_device *rdev,
+                                      struct net_device *netdev,
+                                      const u8 *addr);
 extern void
 nl80211_michael_mic_failure(struct cfg80211_registered_device *rdev,
                            struct net_device *netdev, const u8 *addr,