cfg80211/mac80211: userspace peer authorization in IBSS
If the IBSS network is RSN-protected, let userspace authorize the stations
instead of adding them as AUTHORIZED by default.
Signed-off-by: Antonio Quartulli <ordex@autistici.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 229edc5..e0c9ff3 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1147,6 +1147,10 @@
* @beacon_interval: beacon interval to use
* @privacy: this is a protected network, keys will be configured
* after joining
+ * @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.
* @basic_rates: bitmap of basic rates to use when creating the IBSS
* @mcast_rate: per-band multicast rate index + 1 (0: disabled)
*/
@@ -1161,6 +1165,7 @@
u32 basic_rates;
bool channel_fixed;
bool privacy;
+ bool control_port;
int mcast_rate[IEEE80211_NUM_BANDS];
};
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 7b3a0b0..8361da4 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -268,7 +268,10 @@
sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
- sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
+ /* authorize the station only if the network is not RSN protected. If
+ * not wait for the userspace to authorize it */
+ if (!sta->sdata->u.ibss.control_port)
+ sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
rate_control_rate_init(sta);
@@ -1075,6 +1078,7 @@
sdata->u.ibss.fixed_bssid = false;
sdata->u.ibss.privacy = params->privacy;
+ sdata->u.ibss.control_port = params->control_port;
sdata->u.ibss.basic_rates = params->basic_rates;
memcpy(sdata->vif.bss_conf.mcast_rate, params->mcast_rate,
sizeof(params->mcast_rate));
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index a146b11..74594f0 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -478,6 +478,8 @@
bool fixed_channel;
bool privacy;
+ bool control_port;
+
u8 bssid[ETH_ALEN];
u8 ssid[IEEE80211_MAX_SSID_LEN];
u8 ssid_len, ie_len;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index e1fd1bf9..f1681e2 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2654,13 +2654,6 @@
break;
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_STATION:
- /* disallow things sta doesn't support */
- if (params.plink_action)
- return -EINVAL;
- if (params.ht_capa)
- return -EINVAL;
- if (params.listen_interval >= 0)
- return -EINVAL;
/*
* Don't allow userspace to change the TDLS_PEER flag,
* but silently ignore attempts to change it since we
@@ -2668,7 +2661,15 @@
* to change the flag.
*/
params.sta_flags_mask &= ~BIT(NL80211_STA_FLAG_TDLS_PEER);
-
+ /* fall through */
+ case NL80211_IFTYPE_ADHOC:
+ /* disallow things sta doesn't support */
+ if (params.plink_action)
+ return -EINVAL;
+ if (params.ht_capa)
+ return -EINVAL;
+ if (params.listen_interval >= 0)
+ return -EINVAL;
/* reject any changes other than AUTHORIZED */
if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
return -EINVAL;
@@ -4802,6 +4803,9 @@
return PTR_ERR(connkeys);
}
+ ibss.control_port =
+ nla_get_flag(info->attrs[NL80211_ATTR_CONTROL_PORT]);
+
err = cfg80211_join_ibss(rdev, dev, &ibss, connkeys);
if (err)
kfree(connkeys);