Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 496f6e1b authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "cfg80211/nl80211: Optional authentication offload to userspace"

parents 199252c3 d041a1ab
Loading
Loading
Loading
Loading
+51 −3
Original line number Diff line number Diff line
@@ -1878,11 +1878,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),
	CONNECT_REQ_EXTERNAL_AUTH_SUPPORT	= BIT(3),
};

/**
@@ -2553,6 +2558,33 @@ struct cfg80211_nan_func {
	u64 cookie;
};

/**
 * 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
 *
@@ -2862,6 +2894,9 @@ struct cfg80211_nan_func {
 *	All other parameters must be ignored.
 *
 * @set_multicast_to_unicast: configure multicast to unicast conversion for BSS
 *
 * @external_auth: indicates result of offloaded authentication processing from
 *     user space
 */
struct cfg80211_ops {
	int	(*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3146,6 +3181,8 @@ struct cfg80211_ops {
	int	(*set_multicast_to_unicast)(struct wiphy *wiphy,
					    struct net_device *dev,
					    const bool enabled);
	int     (*external_auth)(struct wiphy *wiphy, struct net_device *dev,
				 struct cfg80211_external_auth_params *params);
};

/*
@@ -6085,6 +6122,17 @@ void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info);
 */
bool cfg80211_is_gratuitous_arp_unsolicited_na(struct sk_buff *skb);

/**
 * 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 */
+70 −0
Original line number Diff line number Diff line
@@ -944,6 +944,43 @@
 *	does not result in a change for the current association. Currently,
 *	only the %NL80211_ATTR_IE data is used and updated with this command.
 *
 * @NL80211_CMD_SET_PMK: For offloaded 4-Way handshake, set the PMK or PMK-R0
 *	for the given authenticator address (specified with &NL80211_ATTR_MAC).
 *	When &NL80211_ATTR_PMKR0_NAME is set, &NL80211_ATTR_PMK specifies the
 *	PMK-R0, otherwise it specifies the PMK.
 * @NL80211_CMD_DEL_PMK: For offloaded 4-Way handshake, delete the previously
 *	configured PMK for the authenticator address identified by
 *	&NL80211_ATTR_MAC.
 * @NL80211_CMD_PORT_AUTHORIZED: An event that indicates that the 4 way
 *	handshake was completed successfully by the driver. The BSSID is
 *	specified with &NL80211_ATTR_MAC. Drivers that support 4 way handshake
 *	offload should send this event after indicating 802.11 association with
 *	&NL80211_CMD_CONNECT or &NL80211_CMD_ROAM. If the 4 way handshake failed
 *	&NL80211_CMD_DISCONNECT should be indicated instead.
 *
 * @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
 */
@@ -1143,6 +1180,15 @@ enum nl80211_commands {

	NL80211_CMD_UPDATE_CONNECT_PARAMS,

	NL80211_CMD_SET_PMK,
	NL80211_CMD_DEL_PMK,

	NL80211_CMD_PORT_AUTHORIZED,

	NL80211_CMD_RELOAD_REGDB,

	NL80211_CMD_EXTERNAL_AUTH,

	/* add new commands above here */

	/* used to define NL80211_CMD_MAX below */
@@ -2079,6 +2125,16 @@ enum nl80211_commands {
 *	the driver or is not needed (because roaming used the Fast Transition
 *	protocol).
 *
 * @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
@@ -2505,6 +2561,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,
@@ -5403,4 +5462,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 */
+92 −0
Original line number Diff line number Diff line
@@ -434,6 +434,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
					.len = FILS_ERP_MAX_RRK_LEN },
	[NL80211_ATTR_FILS_CACHE_ID] = { .len = 2 },
	[NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
	[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG },
};

/* policy for the key attributes */
@@ -8887,6 +8888,13 @@ 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]) {
			return -EINVAL;
		}
		connect.flags |= CONNECT_REQ_EXTERNAL_AUTH_SUPPORT;
	}

	wdev_lock(dev->ieee80211_ptr);

	err = cfg80211_connect(rdev, dev, &connect, connkeys,
@@ -12043,6 +12051,41 @@ static int nl80211_set_multicast_to_unicast(struct sk_buff *skb,
	return rdev_set_multicast_to_unicast(rdev, dev, enabled);
}

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
@@ -12932,6 +12975,14 @@ static const struct genl_ops nl80211_ops[] = {
		.internal_flags = NL80211_FLAG_NEED_NETDEV |
				  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,
	},
};

/* notification functions */
@@ -14925,6 +14976,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 nl80211_init(void)
+15 −0
Original line number Diff line number Diff line
@@ -1153,4 +1153,19 @@ rdev_set_coalesce(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 */
+23 −0
Original line number Diff line number Diff line
@@ -2230,6 +2230,29 @@ TRACE_EVENT(rdev_tdls_cancel_channel_switch,
		  WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(addr))
);

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		     *
 *************************************************************/