nl80211: Add IEEE 802.1X PAE control for station mode
authorJouni Malinen <jouni.malinen@atheros.com>
Mon, 11 May 2009 18:57:57 +0000 (21:57 +0300)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 13 May 2009 19:44:37 +0000 (15:44 -0400)
Add a new NL80211_ATTR_CONTROL_PORT flag for NL80211_CMD_ASSOCIATE to
allow user space to indicate that it will control the IEEE 802.1X port
in station mode. Previously, mac80211 was always marking the port
authorized in station mode. This was enough when drop_unencrypted flag
was set. However, drop_unencrypted can currently be controlled only
with WEXT and the current nl80211 design does not allow fully secure
configuration. Fix this by providing a mechanism for user space to
control the IEEE 802.1X port in station mode (i.e., do the same that
we are already doing in AP mode).

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/cfg.c
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c
net/mac80211/wext.c
net/wireless/nl80211.c

index aeefccfac0e14dfc0801ef1ff1b84f0bc1a9468f..2781525b03d5d450aa750beea60a95ec0a9b8e09 100644 (file)
@@ -504,6 +504,13 @@ enum nl80211_commands {
  * @NL80211_ATTR_STA_FLAGS2: Attribute containing a
  *     &struct nl80211_sta_flag_update.
  *
+ * @NL80211_ATTR_CONTROL_PORT: A flag indicating whether user space controls
+ *     IEEE 802.1X port, i.e., sets/clears %NL80211_STA_FLAG_AUTHORIZED, in
+ *     station mode. If the flag is included in %NL80211_CMD_ASSOCIATE
+ *     request, the driver will assume that the port is unauthorized until
+ *     authorized by user space. Otherwise, port is marked authorized by
+ *     default in station mode.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -610,6 +617,8 @@ enum nl80211_attrs {
 
        NL80211_ATTR_STA_FLAGS2,
 
+       NL80211_ATTR_CONTROL_PORT,
+
        /* add attributes here, update the policy in nl80211.c */
 
        __NL80211_ATTR_AFTER_LAST,
index 0dae6b3829405e66142239e3a949930a8c7d14b0..9e17a83d3432dcc4a79588b1a2b2e36c75764104 100644 (file)
@@ -655,6 +655,10 @@ struct cfg80211_auth_request {
  * @ie: Extra IEs to add to (Re)Association Request frame or %NULL
  * @ie_len: Length of ie buffer in octets
  * @use_mfp: Use management frame protection (IEEE 802.11w) in this association
+ * @control_port: Whether user space controls IEEE 802.1X port, i.e.,
+ *     sets/clears %NL80211_STA_FLAG_AUTHORIZED. If true, the driver is
+ *     required to assume that the port is unauthorized until authorized by
+ *     user space. Otherwise, port is marked authorized by default.
  */
 struct cfg80211_assoc_request {
        struct ieee80211_channel *chan;
@@ -664,6 +668,7 @@ struct cfg80211_assoc_request {
        const u8 *ie;
        size_t ie_len;
        bool use_mfp;
+       bool control_port;
 };
 
 /**
index d591a936f5c43fea4b51393d531e365637a482fd..6464bfd232c946c13972fd69c9bd7035bfbea8c5 100644 (file)
@@ -1265,6 +1265,11 @@ static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev,
                sdata->u.mgd.flags &= ~IEEE80211_STA_MFP_ENABLED;
        }
 
+       if (req->control_port)
+               sdata->u.mgd.flags |= IEEE80211_STA_CONTROL_PORT;
+       else
+               sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
+
        sdata->u.mgd.flags |= IEEE80211_STA_EXT_SME;
        sdata->u.mgd.state = IEEE80211_STA_MLME_ASSOCIATE;
        ieee80211_sta_req_auth(sdata);
index 081c57427308587b0dc2515e0d225773a2c06b8a..56a49ef446ca873b736f4bfe420d8286aceed034 100644 (file)
@@ -235,7 +235,7 @@ struct mesh_preq_queue {
 #define IEEE80211_STA_ASSOCIATED       BIT(4)
 #define IEEE80211_STA_PROBEREQ_POLL    BIT(5)
 #define IEEE80211_STA_CREATE_IBSS      BIT(6)
-/* hole at 7, please re-use */
+#define IEEE80211_STA_CONTROL_PORT     BIT(7)
 #define IEEE80211_STA_WMM_ENABLED      BIT(8)
 /* hole at 9, please re-use */
 #define IEEE80211_STA_AUTO_SSID_SEL    BIT(10)
index 6d00e3f738c0eb3ae4c58f0602538b33506d0032..2806f6af7ae7676e081cf5e197c8456f5deac4fa 100644 (file)
@@ -1581,8 +1581,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
         *        to between the sta_info_alloc() and sta_info_insert() above.
         */
 
-       set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP |
-                          WLAN_STA_AUTHORIZED);
+       set_sta_flags(sta, WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_AP);
+       if (!(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
+               set_sta_flags(sta, WLAN_STA_AUTHORIZED);
 
        rates = 0;
        basic_rates = 0;
index d845026446863f404d5fe88dfe955ecb9437c77c..c14394744a9c321b3a2b73d26d448c8bd7242361 100644 (file)
@@ -41,6 +41,7 @@ static int ieee80211_ioctl_siwgenie(struct net_device *dev,
                        return ret;
                sdata->u.mgd.flags &= ~IEEE80211_STA_AUTO_BSSID_SEL;
                sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
+               sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
                ieee80211_sta_req_auth(sdata);
                return 0;
        }
@@ -124,6 +125,7 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev,
                        return ret;
 
                sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
+               sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
                ieee80211_sta_req_auth(sdata);
                return 0;
        }
@@ -181,6 +183,7 @@ static int ieee80211_ioctl_siwap(struct net_device *dev,
                if (ret)
                        return ret;
                sdata->u.mgd.flags &= ~IEEE80211_STA_EXT_SME;
+               sdata->u.mgd.flags &= ~IEEE80211_STA_CONTROL_PORT;
                ieee80211_sta_req_auth(sdata);
                return 0;
        } else if (sdata->vif.type == NL80211_IFTYPE_WDS) {
index 66024ef57bab684900ac79cb714c1672a61b027c..cad281390cfa2750fcedafc4285b9a7137fa687e 100644 (file)
@@ -126,6 +126,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
        [NL80211_ATTR_STA_FLAGS2] = {
                .len = sizeof(struct nl80211_sta_flag_update),
        },
+       [NL80211_ATTR_CONTROL_PORT] = { .type = NLA_FLAG },
 };
 
 /* IE validation */
@@ -3040,6 +3041,8 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info)
                }
        }
 
+       req.control_port = info->attrs[NL80211_ATTR_CONTROL_PORT];
+
        err = drv->ops->assoc(&drv->wiphy, dev, &req);
 
 out: