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

Commit 9ddb378b authored by Xinming Hu's avatar Xinming Hu Committed by Kalle Valo
Browse files

mwifiex: correct IE parse during association



It is observed that some IEs get missed during association.
This patch correct the old IE parse code. sme->ie will be
store as wpa ie, wps ie, wapi ie and gen ie accordingly.

Signed-off-by: default avatarXinming Hu <huxm@marvell.com>
Signed-off-by: default avatarCathy Luo <cluo@marvell.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
parent fc81bab5
Loading
Loading
Loading
Loading
+55 −60
Original line number Diff line number Diff line
@@ -811,7 +811,7 @@ int mwifiex_drv_set_power(struct mwifiex_private *priv, u32 *ps_mode)
 * is checked to determine WPA version. If buffer length is zero, the existing
 * WPA IE is reset.
 */
static int mwifiex_set_wpa_ie_helper(struct mwifiex_private *priv,
static int mwifiex_set_wpa_ie(struct mwifiex_private *priv,
			      u8 *ie_data_ptr, u16 ie_len)
{
	if (ie_len) {
@@ -1351,101 +1351,96 @@ static int
mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr,
			  u16 ie_len)
{
	int ret = 0;
	struct ieee_types_vendor_header *pvendor_ie;
	const u8 wpa_oui[] = { 0x00, 0x50, 0xf2, 0x01 };
	const u8 wps_oui[] = { 0x00, 0x50, 0xf2, 0x04 };
	u16 unparsed_len = ie_len;
	int find_wpa_ie = 0;
	u16 unparsed_len = ie_len, cur_ie_len;

	/* If the passed length is zero, reset the buffer */
	if (!ie_len) {
		priv->gen_ie_buf_len = 0;
		priv->wps.session_enable = false;

		return 0;
	} else if (!ie_data_ptr) {
	} else if (!ie_data_ptr ||
		   ie_len <= sizeof(struct ieee_types_header)) {
		return -1;
	}
	pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr;

	while (pvendor_ie) {
		cur_ie_len = pvendor_ie->len + sizeof(struct ieee_types_header);

		if (pvendor_ie->element_id == WLAN_EID_RSN) {
			/* IE is a WPA/WPA2 IE so call set_wpa function */
			mwifiex_set_wpa_ie(priv, (u8 *)pvendor_ie, cur_ie_len);
			priv->wps.session_enable = false;
			goto next_ie;
		}

		if (pvendor_ie->element_id == WLAN_EID_BSS_AC_ACCESS_DELAY) {
			/* IE is a WAPI IE so call set_wapi function */
			mwifiex_set_wapi_ie(priv, (u8 *)pvendor_ie,
					    cur_ie_len);
			goto next_ie;
		}

		if (pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) {
			/* Test to see if it is a WPA IE, if not, then it is a
			 * gen IE
			/* Test to see if it is a WPA IE, if not, then
			 * it is a gen IE
			 */
			if (!memcmp(pvendor_ie->oui, wpa_oui,
				    sizeof(wpa_oui))) {
				find_wpa_ie = 1;
				break;
				/* IE is a WPA/WPA2 IE so call set_wpa function
				 */
				mwifiex_set_wpa_ie(priv, (u8 *)pvendor_ie,
						   cur_ie_len);
				priv->wps.session_enable = false;
				goto next_ie;
			}

			/* Test to see if it is a WPS IE, if so, enable
			 * wps session flag
			 */
			if (!memcmp(pvendor_ie->oui, wps_oui,
				    sizeof(wps_oui))) {
				/* Test to see if it is a WPS IE,
				 * if so, enable wps session flag
				 */
				priv->wps.session_enable = true;
				mwifiex_dbg(priv->adapter, MSG,
					    "info: WPS Session Enabled.\n");
				ret = mwifiex_set_wps_ie(priv,
							 (u8 *)pvendor_ie,
							 unparsed_len);
					    "WPS Session Enabled.\n");
				mwifiex_set_wps_ie(priv, (u8 *)pvendor_ie,
						   cur_ie_len);
				goto next_ie;
			}
		}

		if (pvendor_ie->element_id == WLAN_EID_RSN) {
			find_wpa_ie = 1;
			break;
		}
		/* Saved in gen_ie, such as P2P IE.etc.*/

		if (pvendor_ie->element_id == WLAN_EID_BSS_AC_ACCESS_DELAY) {
		/* IE is a WAPI IE so call set_wapi function */
			ret = mwifiex_set_wapi_ie(priv, (u8 *)pvendor_ie,
						  unparsed_len);
			return ret;
		/* Verify that the passed length is not larger than the
		 * available space remaining in the buffer
		 */
		if (cur_ie_len <
		    (sizeof(priv->gen_ie_buf) - priv->gen_ie_buf_len)) {
			/* Append the passed data to the end
			 * of the genIeBuffer
			 */
			memcpy(priv->gen_ie_buf + priv->gen_ie_buf_len,
			       (u8 *)pvendor_ie, cur_ie_len);
			/* Increment the stored buffer length by the
			 * size passed
			 */
			priv->gen_ie_buf_len += cur_ie_len;
		}

		unparsed_len -= (pvendor_ie->len +
				 sizeof(struct ieee_types_header));
next_ie:
		unparsed_len -= cur_ie_len;

		if (unparsed_len <= sizeof(struct ieee_types_header))
			pvendor_ie = NULL;
		else
			pvendor_ie = (struct ieee_types_vendor_header *)
				(((u8 *)pvendor_ie) + pvendor_ie->len +
				 sizeof(struct ieee_types_header));
	}

	if (find_wpa_ie) {
		/* IE is a WPA/WPA2 IE so call set_wpa function */
		ret = mwifiex_set_wpa_ie_helper(priv, (u8 *)pvendor_ie,
						unparsed_len);
		priv->wps.session_enable = false;
		return ret;
				(((u8 *)pvendor_ie) + cur_ie_len);
	}

	/*
	 * Verify that the passed length is not larger than the
	 * available space remaining in the buffer
	 */
	if (ie_len < (sizeof(priv->gen_ie_buf) - priv->gen_ie_buf_len)) {

		/* Append the passed data to the end of the
		   genIeBuffer */
		memcpy(priv->gen_ie_buf + priv->gen_ie_buf_len, ie_data_ptr,
		       ie_len);
		/* Increment the stored buffer length by the
		   size passed */
		priv->gen_ie_buf_len += ie_len;
	} else {
		/* Passed data does not fit in the remaining
		   buffer space */
		ret = -1;
	}

	/* Return 0, or -1 for error case */
	return ret;
	return 0;
}

/*