aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/net/cfg80211.h54
-rw-r--r--include/uapi/linux/nl80211.h47
-rw-r--r--net/wireless/nl80211.c94
-rw-r--r--net/wireless/rdev-ops.h15
-rw-r--r--net/wireless/trace.h23
5 files changed, 230 insertions, 3 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 81174f9b8d14..68def3e5b013 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1905,11 +1905,16 @@ struct cfg80211_auth_request {
* @ASSOC_REQ_DISABLE_HT: Disable HT (802.11n)
* @ASSOC_REQ_DISABLE_VHT: Disable VHT
* @ASSOC_REQ_USE_RRM: Declare RRM capability in this association
+ * @CONNECT_REQ_EXTERNAL_AUTH_SUPPORT: User space indicates external
+ * authentication capability. Drivers can offload authentication to
+ * userspace if this flag is set. Only applicable for cfg80211_connect()
+ * request (connect callback).
*/
enum cfg80211_assoc_req_flags {
- ASSOC_REQ_DISABLE_HT = BIT(0),
- ASSOC_REQ_DISABLE_VHT = BIT(1),
- ASSOC_REQ_USE_RRM = BIT(2),
+ ASSOC_REQ_DISABLE_HT = BIT(0),
+ ASSOC_REQ_DISABLE_VHT = BIT(1),
+ ASSOC_REQ_USE_RRM = BIT(2),
+ CONNECT_REQ_EXTERNAL_AUTH_SUPPORT = BIT(3),
};
/**
@@ -2601,6 +2606,33 @@ struct cfg80211_pmk_conf {
};
/**
+ * struct cfg80211_external_auth_params - Trigger External authentication.
+ *
+ * Commonly used across the external auth request and event interfaces.
+ *
+ * @action: action type / trigger for external authentication. Only significant
+ * for the authentication request event interface (driver to user space).
+ * @bssid: BSSID of the peer with which the authentication has
+ * to happen. Used by both the authentication request event and
+ * authentication response command interface.
+ * @ssid: SSID of the AP. Used by both the authentication request event and
+ * authentication response command interface.
+ * @key_mgmt_suite: AKM suite of the respective authentication. Used by the
+ * authentication request event interface.
+ * @status: status code, %WLAN_STATUS_SUCCESS for successful authentication,
+ * use %WLAN_STATUS_UNSPECIFIED_FAILURE if user space cannot give you
+ * the real status code for failures. Used only for the authentication
+ * response command interface (user space to driver).
+ */
+struct cfg80211_external_auth_params {
+ enum nl80211_external_auth_action action;
+ u8 bssid[ETH_ALEN] __aligned(2);
+ struct cfg80211_ssid ssid;
+ unsigned int key_mgmt_suite;
+ u16 status;
+};
+
+/**
* struct cfg80211_ops - backend description for wireless configuration
*
* This struct is registered by fullmac card drivers and/or wireless stacks
@@ -2923,6 +2955,9 @@ struct cfg80211_pmk_conf {
* (invoked with the wireless_dev mutex held)
* @del_pmk: delete the previously configured PMK for the given authenticator.
* (invoked with the wireless_dev mutex held)
+ *
+ * @external_auth: indicates result of offloaded authentication processing from
+ * user space
*/
struct cfg80211_ops {
int (*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3216,6 +3251,8 @@ struct cfg80211_ops {
const struct cfg80211_pmk_conf *conf);
int (*del_pmk)(struct wiphy *wiphy, struct net_device *dev,
const u8 *aa);
+ int (*external_auth)(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_external_auth_params *params);
};
/*
@@ -6202,6 +6239,17 @@ void cfg80211_nan_func_terminated(struct wireless_dev *wdev,
/* ethtool helper */
void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info);
+/**
+ * cfg80211_external_auth_request - userspace request for authentication
+ * @netdev: network device
+ * @params: External authentication parameters
+ * @gfp: allocation flags
+ * Returns: 0 on success, < 0 on error
+ */
+int cfg80211_external_auth_request(struct net_device *netdev,
+ struct cfg80211_external_auth_params *params,
+ gfp_t gfp);
+
/* Logging, debugging and troubleshooting/diagnostic helpers. */
/* wiphy_printk helpers, similar to dev_printk */
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 6f60503fa617..c2342456cf16 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -992,6 +992,27 @@
*
* @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded.
*
+ * @NL80211_CMD_EXTERNAL_AUTH: This interface is exclusively defined for host
+ * drivers that do not define separate commands for authentication and
+ * association, but rely on user space for the authentication to happen.
+ * This interface acts both as the event request (driver to user space)
+ * to trigger the authentication and command response (userspace to
+ * driver) to indicate the authentication status.
+ *
+ * User space uses the %NL80211_CMD_CONNECT command to the host driver to
+ * trigger a connection. The host driver selects a BSS and further uses
+ * this interface to offload only the authentication part to the user
+ * space. Authentication frames are passed between the driver and user
+ * space through the %NL80211_CMD_FRAME interface. Host driver proceeds
+ * further with the association after getting successful authentication
+ * status. User space indicates the authentication status through
+ * %NL80211_ATTR_STATUS_CODE attribute in %NL80211_CMD_EXTERNAL_AUTH
+ * command interface.
+ *
+ * Host driver reports this status on an authentication failure to the
+ * user space through the connect result as the user space would have
+ * initiated the connection through the connect request.
+ *
* @NL80211_CMD_MAX: highest used command number
* @__NL80211_CMD_AFTER_LAST: internal use
*/
@@ -1198,6 +1219,8 @@ enum nl80211_commands {
NL80211_CMD_RELOAD_REGDB,
+ NL80211_CMD_EXTERNAL_AUTH,
+
/* add new commands above here */
/* used to define NL80211_CMD_MAX below */
@@ -2153,6 +2176,16 @@ enum nl80211_commands {
* @NL80211_ATTR_PMKR0_NAME: PMK-R0 Name for offloaded FT.
* @NL80211_ATTR_PORT_AUTHORIZED: (reserved)
*
+ * @NL80211_ATTR_EXTERNAL_AUTH_ACTION: Identify the requested external
+ * authentication operation (u32 attribute with an
+ * &enum nl80211_external_auth_action value). This is used with the
+ * &NL80211_CMD_EXTERNAL_AUTH request event.
+ * @NL80211_ATTR_EXTERNAL_AUTH_SUPPORT: Flag attribute indicating that the user
+ * space supports external authentication. This attribute shall be used
+ * only with %NL80211_CMD_CONNECT request. The driver may offload
+ * authentication processing to user space if this capability is indicated
+ * in NL80211_CMD_CONNECT requests from the user space.
+ *
* @NUM_NL80211_ATTR: total number of nl80211_attrs available
* @NL80211_ATTR_MAX: highest attribute number currently defined
* @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2579,6 +2612,9 @@ enum nl80211_attrs {
NL80211_ATTR_PMKR0_NAME,
NL80211_ATTR_PORT_AUTHORIZED,
+ NL80211_ATTR_EXTERNAL_AUTH_ACTION,
+ NL80211_ATTR_EXTERNAL_AUTH_SUPPORT,
+
/* add attributes here, update the policy in nl80211.c */
__NL80211_ATTR_AFTER_LAST,
@@ -5495,4 +5531,15 @@ enum nl80211_nan_match_attributes {
NL80211_NAN_MATCH_ATTR_MAX = NUM_NL80211_NAN_MATCH_ATTR - 1
};
+/**
+ * nl80211_external_auth_action - Action to perform with external
+ * authentication request. Used by NL80211_ATTR_EXTERNAL_AUTH_ACTION.
+ * @NL80211_EXTERNAL_AUTH_START: Start the authentication.
+ * @NL80211_EXTERNAL_AUTH_ABORT: Abort the ongoing authentication.
+ */
+enum nl80211_external_auth_action {
+ NL80211_EXTERNAL_AUTH_START,
+ NL80211_EXTERNAL_AUTH_ABORT,
+};
+
#endif /* __LINUX_NL80211_H */
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index dd249ec9f228..aa6b64069c80 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -420,6 +420,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_FILS_CACHE_ID] = { .len = 2 },
[NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
[NL80211_ATTR_SCHED_SCAN_MULTI] = { .type = NLA_FLAG },
+ [NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG },
};
/* policy for the key attributes */
@@ -9161,6 +9162,15 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
}
+ if (nla_get_flag(info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])) {
+ if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
+ GENL_SET_ERR_MSG(info,
+ "external auth requires connection ownership");
+ return -EINVAL;
+ }
+ connect.flags |= CONNECT_REQ_EXTERNAL_AUTH_SUPPORT;
+ }
+
wdev_lock(dev->ieee80211_ptr);
err = cfg80211_connect(rdev, dev, &connect, connkeys,
@@ -12469,6 +12479,41 @@ static int nl80211_del_pmk(struct sk_buff *skb, struct genl_info *info)
return ret;
}
+static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info)
+{
+ struct cfg80211_registered_device *rdev = info->user_ptr[0];
+ struct net_device *dev = info->user_ptr[1];
+ struct cfg80211_external_auth_params params;
+
+ if (rdev->ops->external_auth)
+ return -EOPNOTSUPP;
+
+ if (!info->attrs[NL80211_ATTR_SSID])
+ return -EINVAL;
+
+ if (!info->attrs[NL80211_ATTR_BSSID])
+ return -EINVAL;
+
+ if (!info->attrs[NL80211_ATTR_STATUS_CODE])
+ return -EINVAL;
+
+ memset(&params, 0, sizeof(params));
+
+ params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
+ if (params.ssid.ssid_len == 0 ||
+ params.ssid.ssid_len > IEEE80211_MAX_SSID_LEN)
+ return -EINVAL;
+ memcpy(params.ssid.ssid, nla_data(info->attrs[NL80211_ATTR_SSID]),
+ params.ssid.ssid_len);
+
+ memcpy(params.bssid, nla_data(info->attrs[NL80211_ATTR_BSSID]),
+ ETH_ALEN);
+
+ params.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
+
+ return rdev_external_auth(rdev, dev, &params);
+}
+
#define NL80211_FLAG_NEED_WIPHY 0x01
#define NL80211_FLAG_NEED_NETDEV 0x02
#define NL80211_FLAG_NEED_RTNL 0x04
@@ -13364,6 +13409,14 @@ static const struct genl_ops nl80211_ops[] = {
.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
NL80211_FLAG_NEED_RTNL,
},
+ {
+ .cmd = NL80211_CMD_EXTERNAL_AUTH,
+ .doit = nl80211_external_auth,
+ .policy = nl80211_policy,
+ .flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+ NL80211_FLAG_NEED_RTNL,
+ },
};
@@ -15375,6 +15428,47 @@ void nl80211_send_ap_stopped(struct wireless_dev *wdev)
nlmsg_free(msg);
}
+int cfg80211_external_auth_request(struct net_device *dev,
+ struct cfg80211_external_auth_params *params,
+ gfp_t gfp)
+{
+ struct wireless_dev *wdev = dev->ieee80211_ptr;
+ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+ struct sk_buff *msg;
+ void *hdr;
+
+ if (!wdev->conn_owner_nlportid)
+ return -EINVAL;
+
+ msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+ if (!msg)
+ return -ENOMEM;
+
+ hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_EXTERNAL_AUTH);
+ if (!hdr)
+ goto nla_put_failure;
+
+ if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+ nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
+ nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, params->key_mgmt_suite) ||
+ nla_put_u32(msg, NL80211_ATTR_EXTERNAL_AUTH_ACTION,
+ params->action) ||
+ nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid) ||
+ nla_put(msg, NL80211_ATTR_SSID, params->ssid.ssid_len,
+ params->ssid.ssid))
+ goto nla_put_failure;
+
+ genlmsg_end(msg, hdr);
+ genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
+ wdev->conn_owner_nlportid);
+ return 0;
+
+ nla_put_failure:
+ nlmsg_free(msg);
+ return -ENOBUFS;
+}
+EXPORT_SYMBOL(cfg80211_external_auth_request);
+
/* initialisation/exit functions */
int __init nl80211_init(void)
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 0c06240d25af..84f23ae015fc 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -1190,4 +1190,19 @@ static inline int rdev_del_pmk(struct cfg80211_registered_device *rdev,
trace_rdev_return_int(&rdev->wiphy, ret);
return ret;
}
+
+static inline int
+rdev_external_auth(struct cfg80211_registered_device *rdev,
+ struct net_device *dev,
+ struct cfg80211_external_auth_params *params)
+{
+ int ret = -EOPNOTSUPP;
+
+ trace_rdev_external_auth(&rdev->wiphy, dev, params);
+ if (rdev->ops->external_auth)
+ ret = rdev->ops->external_auth(&rdev->wiphy, dev, params);
+ trace_rdev_return_int(&rdev->wiphy, ret);
+ return ret;
+}
+
#endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index bcfedd39e7a3..5152938b358d 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2319,6 +2319,29 @@ TRACE_EVENT(rdev_del_pmk,
WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(aa))
);
+TRACE_EVENT(rdev_external_auth,
+ TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+ struct cfg80211_external_auth_params *params),
+ TP_ARGS(wiphy, netdev, params),
+ TP_STRUCT__entry(WIPHY_ENTRY
+ NETDEV_ENTRY
+ MAC_ENTRY(bssid)
+ __array(u8, ssid, IEEE80211_MAX_SSID_LEN + 1)
+ __field(u16, status)
+ ),
+ TP_fast_assign(WIPHY_ASSIGN;
+ NETDEV_ASSIGN;
+ MAC_ASSIGN(bssid, params->bssid);
+ memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1);
+ memcpy(__entry->ssid, params->ssid.ssid,
+ params->ssid.ssid_len);
+ __entry->status = params->status;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT
+ ", ssid: %s, status: %u", WIPHY_PR_ARG, NETDEV_PR_ARG,
+ __entry->bssid, __entry->ssid, __entry->status)
+);
+
/*************************************************************
* cfg80211 exported functions traces *
*************************************************************/