return NULL;
}
-static int
-rtw_ieee802_11_parse_vendor_specific(u8 *pos, uint elen,
- struct rtw_ieee802_11_elems *elems,
- int show_errors)
-{
- unsigned int oui;
-
- /* first 3 bytes in vendor specific information element are the IEEE
- * OUI of the vendor. The following byte is used a vendor specific
- * sub-type. */
- if (elen < 4) {
- if (show_errors) {
- DBG_8723A("short vendor specific "
- "information element ignored (len =%lu)\n",
- (unsigned long) elen);
- }
- return -1;
- }
-
- oui = RTW_GET_BE24(pos);
- switch (oui) {
- case WLAN_OUI_MICROSOFT:
- /* Microsoft/Wi-Fi information elements are further typed and
- * subtyped */
- switch (pos[3]) {
- case 1:
- /* Microsoft OUI (00:50:F2) with OUI Type 1:
- * real WPA information element */
- elems->wpa_ie = pos;
- elems->wpa_ie_len = elen;
- break;
- case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */
- if (elen < 5) {
- DBG_8723A("short WME "
- "information element ignored "
- "(len =%lu)\n",
- (unsigned long) elen);
- return -1;
- }
- switch (pos[4]) {
- case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
- case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
- elems->wme = pos;
- elems->wme_len = elen;
- break;
- case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
- elems->wme_tspec = pos;
- elems->wme_tspec_len = elen;
- break;
- default:
- DBG_8723A("unknown WME "
- "information element ignored "
- "(subtype =%d len =%lu)\n",
- pos[4], (unsigned long) elen);
- return -1;
- }
- break;
- case 4:
- /* Wi-Fi Protected Setup (WPS) IE */
- elems->wps_ie = pos;
- elems->wps_ie_len = elen;
- break;
- default:
- DBG_8723A("Unknown Microsoft "
- "information element ignored "
- "(type =%d len =%lu)\n",
- pos[3], (unsigned long) elen);
- return -1;
- }
- break;
-
- case OUI_BROADCOM:
- switch (pos[3]) {
- case VENDOR_HT_CAPAB_OUI_TYPE:
- elems->vendor_ht_cap = pos;
- elems->vendor_ht_cap_len = elen;
- break;
- default:
- DBG_8723A("Unknown Broadcom "
- "information element ignored "
- "(type =%d len =%lu)\n",
- pos[3], (unsigned long) elen);
- return -1;
- }
- break;
-
- default:
- DBG_8723A("unknown vendor specific information "
- "element ignored (vendor OUI %02x:%02x:%02x "
- "len =%lu)\n",
- pos[0], pos[1], pos[2], (unsigned long) elen);
- return -1;
- }
-
- return 0;
-}
-
-/**
- * ieee802_11_parse_elems - Parse information elements in management frames
- * @start: Pointer to the start of IEs
- * @len: Length of IE buffer in octets
- * @elems: Data structure for parsed elements
- * @show_errors: Whether to show parsing errors in debug log
- * Returns: Parsing result
- */
-enum parse_res rtw_ieee802_11_parse_elems23a(u8 *start, uint len,
- struct rtw_ieee802_11_elems *elems,
- int show_errors)
-{
- uint left = len;
- u8 *pos = start;
- int unknown = 0;
-
- memset(elems, 0, sizeof(*elems));
-
- while (left >= 2) {
- u8 id, elen;
-
- id = *pos++;
- elen = *pos++;
- left -= 2;
-
- if (elen > left) {
- if (show_errors) {
- DBG_8723A("IEEE 802.11 element "
- "parse failed (id =%d elen =%d "
- "left =%lu)\n",
- id, elen, (unsigned long) left);
- }
- return ParseFailed;
- }
-
- switch (id) {
- case WLAN_EID_SSID:
- elems->ssid = pos;
- elems->ssid_len = elen;
- break;
- case WLAN_EID_SUPP_RATES:
- elems->supp_rates = pos;
- elems->supp_rates_len = elen;
- break;
- case WLAN_EID_FH_PARAMS:
- elems->fh_params = pos;
- elems->fh_params_len = elen;
- break;
- case WLAN_EID_DS_PARAMS:
- elems->ds_params = pos;
- elems->ds_params_len = elen;
- break;
- case WLAN_EID_CF_PARAMS:
- elems->cf_params = pos;
- elems->cf_params_len = elen;
- break;
- case WLAN_EID_TIM:
- elems->tim = pos;
- elems->tim_len = elen;
- break;
- case WLAN_EID_IBSS_PARAMS:
- elems->ibss_params = pos;
- elems->ibss_params_len = elen;
- break;
- case WLAN_EID_CHALLENGE:
- elems->challenge = pos;
- elems->challenge_len = elen;
- break;
- case WLAN_EID_ERP_INFO:
- elems->erp_info = pos;
- elems->erp_info_len = elen;
- break;
- case WLAN_EID_EXT_SUPP_RATES:
- elems->ext_supp_rates = pos;
- elems->ext_supp_rates_len = elen;
- break;
- case WLAN_EID_VENDOR_SPECIFIC:
- if (rtw_ieee802_11_parse_vendor_specific(pos, elen,
- elems,
- show_errors))
- unknown++;
- break;
- case WLAN_EID_RSN:
- elems->rsn_ie = pos;
- elems->rsn_ie_len = elen;
- break;
- case WLAN_EID_PWR_CAPABILITY:
- elems->power_cap = pos;
- elems->power_cap_len = elen;
- break;
- case WLAN_EID_SUPPORTED_CHANNELS:
- elems->supp_channels = pos;
- elems->supp_channels_len = elen;
- break;
- case WLAN_EID_MOBILITY_DOMAIN:
- elems->mdie = pos;
- elems->mdie_len = elen;
- break;
- case WLAN_EID_FAST_BSS_TRANSITION:
- elems->ftie = pos;
- elems->ftie_len = elen;
- break;
- case WLAN_EID_TIMEOUT_INTERVAL:
- elems->timeout_int = pos;
- elems->timeout_int_len = elen;
- break;
- case WLAN_EID_HT_CAPABILITY:
- elems->ht_capabilities = pos;
- elems->ht_capabilities_len = elen;
- break;
- case WLAN_EID_HT_OPERATION:
- elems->ht_operation = pos;
- elems->ht_operation_len = elen;
- break;
- default:
- unknown++;
- if (!show_errors)
- break;
- DBG_8723A("IEEE 802.11 element parse "
- "ignored unknown element (id =%d elen =%d)\n",
- id, elen);
- break;
- }
-
- left -= elen;
- pos += elen;
- }
-
- if (left)
- return ParseFailed;
-
- return unknown ? ParseUnknown : ParseOK;
-}
-
static u8 key_char2num(u8 ch)
{
if ((ch >= '0') && (ch <= '9'))
return _FAIL;
}
+#ifdef CONFIG_8723AU_AP_MODE
+static int rtw_validate_vendor_specific_ies(const u8 *pos, int elen)
+{
+ unsigned int oui;
+
+ /* first 3 bytes in vendor specific information element are the IEEE
+ * OUI of the vendor. The following byte is used a vendor specific
+ * sub-type. */
+ if (elen < 4) {
+ DBG_8723A("short vendor specific information element "
+ "ignored (len =%i)\n", elen);
+ return -EINVAL;
+ }
+
+ oui = RTW_GET_BE24(pos);
+ switch (oui) {
+ case WLAN_OUI_MICROSOFT:
+ /* Microsoft/Wi-Fi information elements are further typed and
+ * subtyped */
+ switch (pos[3]) {
+ case 1:
+ /* Microsoft OUI (00:50:F2) with OUI Type 1:
+ * real WPA information element */
+ break;
+ case WME_OUI_TYPE: /* this is a Wi-Fi WME info. element */
+ if (elen < 5) {
+ DBG_8723A("short WME information element "
+ "ignored (len =%i)\n", elen);
+ return -EINVAL;
+ }
+ switch (pos[4]) {
+ case WME_OUI_SUBTYPE_INFORMATION_ELEMENT:
+ case WME_OUI_SUBTYPE_PARAMETER_ELEMENT:
+ break;
+ case WME_OUI_SUBTYPE_TSPEC_ELEMENT:
+ break;
+ default:
+ DBG_8723A("unknown WME information element "
+ "ignored (subtype =%d len =%i)\n",
+ pos[4], elen);
+ return -EINVAL;
+ }
+ break;
+ case 4:
+ /* Wi-Fi Protected Setup (WPS) IE */
+ break;
+ default:
+ DBG_8723A("Unknown Microsoft information element "
+ "ignored (type =%d len =%i)\n",
+ pos[3], elen);
+ return -EINVAL;
+ }
+ break;
+
+ case OUI_BROADCOM:
+ switch (pos[3]) {
+ case VENDOR_HT_CAPAB_OUI_TYPE:
+ break;
+ default:
+ DBG_8723A("Unknown Broadcom information element "
+ "ignored (type =%d len =%i)\n", pos[3], elen);
+ return -EINVAL;
+ }
+ break;
+
+ default:
+ DBG_8723A("unknown vendor specific information element "
+ "ignored (vendor OUI %02x:%02x:%02x len =%i)\n",
+ pos[0], pos[1], pos[2], elen);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int rtw_validate_frame_ies(const u8 *start, uint len)
+{
+ const u8 *pos = start;
+ int left = len;
+ int unknown = 0;
+
+ while (left >= 2) {
+ u8 id, elen;
+
+ id = *pos++;
+ elen = *pos++;
+ left -= 2;
+
+ if (elen > left) {
+ DBG_8723A("%s: IEEE 802.11 failed (id =%d elen =%d "
+ "left =%i)\n", __func__, id, elen, left);
+ return -EINVAL;
+ }
+
+ switch (id) {
+ case WLAN_EID_SSID:
+ case WLAN_EID_SUPP_RATES:
+ case WLAN_EID_FH_PARAMS:
+ case WLAN_EID_DS_PARAMS:
+ case WLAN_EID_CF_PARAMS:
+ case WLAN_EID_TIM:
+ case WLAN_EID_IBSS_PARAMS:
+ case WLAN_EID_CHALLENGE:
+ case WLAN_EID_ERP_INFO:
+ case WLAN_EID_EXT_SUPP_RATES:
+ case WLAN_EID_VENDOR_SPECIFIC:
+ if (rtw_validate_vendor_specific_ies(pos, elen))
+ unknown++;
+ break;
+ case WLAN_EID_RSN:
+ case WLAN_EID_PWR_CAPABILITY:
+ case WLAN_EID_SUPPORTED_CHANNELS:
+ case WLAN_EID_MOBILITY_DOMAIN:
+ case WLAN_EID_FAST_BSS_TRANSITION:
+ case WLAN_EID_TIMEOUT_INTERVAL:
+ case WLAN_EID_HT_CAPABILITY:
+ case WLAN_EID_HT_OPERATION:
+ default:
+ unknown++;
+ DBG_8723A("%s IEEE 802.11 ignored unknown element "
+ "(id =%d elen =%d)\n", __func__, id, elen);
+ break;
+ }
+
+ left -= elen;
+ pos += elen;
+ }
+
+ if (left)
+ return -EINVAL;
+
+ return 0;
+}
+#endif
+
static int
OnAssocReq23a(struct rtw_adapter *padapter, struct recv_frame *precv_frame)
{
#ifdef CONFIG_8723AU_AP_MODE
u16 capab_info, listen_interval;
- struct rtw_ieee802_11_elems elems;
struct sta_info *pstat;
unsigned char reassoc;
unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01};
struct sta_priv *pstapriv = &padapter->stapriv;
struct sk_buff *skb = precv_frame->pkt;
struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) skb->data;
- const u8 *p, *wpa_ie, *wps_ie;
- u8 *pos;
+ const u8 *pos, *p, *wpa_ie, *wps_ie;
u8 *pframe = skb->data;
uint pkt_len = skb->len;
int r;
pstat->capability = capab_info;
/* now parse all ieee802_11 ie to point to elems */
- if (rtw_ieee802_11_parse_elems23a(pos, left, &elems, 1) ==
- ParseFailed) {
+
+ if (rtw_validate_frame_ies(pos, left)) {
DBG_8723A("STA " MAC_FMT " sent invalid association request\n",
MAC_ARG(pstat->hwaddr));
status = WLAN_STATUS_UNSPECIFIED_FAILURE;
pstat->uapsd_be = 0;
pstat->uapsd_bk = 0;
if (pmlmepriv->qospriv.qos_option) {
- u8 *end = pos + left;
+ const u8 *end = pos + left;
p = pos;
for (;;) {