/* This function checks if current IE index is used by any on other interface. * Return: -1: yes, current IE index is used by someone else. * 0: no, current IE index is NOT used by other interface.
*/ staticint
mwifiex_ie_index_used_by_other_intf(struct mwifiex_private *priv, u16 idx)
{ int i; struct mwifiex_adapter *adapter = priv->adapter; struct mwifiex_ie *ie;
for (i = 0; i < adapter->priv_num; i++) { if (adapter->priv[i] != priv) {
ie = &adapter->priv[i]->mgmt_ie[idx]; if (ie->mgmt_subtype_mask && ie->ie_length) return -1;
}
}
return 0;
}
/* Get unused IE index. This index will be used for setting new IE */ staticint
mwifiex_ie_get_autoidx(struct mwifiex_private *priv, u16 subtype_mask, struct mwifiex_ie *ie, u16 *index)
{
u16 mask, len, i;
for (i = 0; i < priv->adapter->max_mgmt_ie_index; i++) {
mask = le16_to_cpu(priv->mgmt_ie[i].mgmt_subtype_mask);
len = le16_to_cpu(ie->ie_length);
if (mask == MWIFIEX_AUTO_IDX_MASK) continue;
if (mask == subtype_mask) { if (len > IEEE_MAX_IE_SIZE) continue;
*index = i; return 0;
}
if (!priv->mgmt_ie[i].ie_length) { if (mwifiex_ie_index_used_by_other_intf(priv, i)) continue;
*index = i; return 0;
}
}
return -1;
}
/* This function prepares IE data buffer for command to be sent to FW */ staticint
mwifiex_update_autoindex_ies(struct mwifiex_private *priv, struct mwifiex_ie_list *ie_list)
{
u16 travel_len, index, mask;
s16 input_len, tlv_len; struct mwifiex_ie *ie;
u8 *tmp;
ie->ie_index = cpu_to_le16(index);
} else { if (mask != MWIFIEX_DELETE_MASK) return -1; /* * Check if this index is being used on any * other interface.
*/ if (mwifiex_ie_index_used_by_other_intf(priv, index)) return -1;
if (beacon_ie) {
len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE +
le16_to_cpu(beacon_ie->ie_length);
memcpy(pos, beacon_ie, len);
pos += len;
le16_unaligned_add_cpu(&ap_custom_ie->len, len);
} if (pr_ie) {
len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE +
le16_to_cpu(pr_ie->ie_length);
memcpy(pos, pr_ie, len);
pos += len;
le16_unaligned_add_cpu(&ap_custom_ie->len, len);
} if (ar_ie) {
len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE +
le16_to_cpu(ar_ie->ie_length);
memcpy(pos, ar_ie, len);
pos += len;
le16_unaligned_add_cpu(&ap_custom_ie->len, len);
}
ret = mwifiex_update_autoindex_ies(priv, ap_custom_ie);
pos = (u8 *)(&ap_custom_ie->ie_list[0].ie_index); if (beacon_ie && *beacon_idx == MWIFIEX_AUTO_IDX_MASK) { /* save beacon ie index after auto-indexing */
*beacon_idx = le16_to_cpu(ap_custom_ie->ie_list[0].ie_index);
len = sizeof(*beacon_ie) - IEEE_MAX_IE_SIZE +
le16_to_cpu(beacon_ie->ie_length);
pos += len;
} if (pr_ie && le16_to_cpu(pr_ie->ie_index) == MWIFIEX_AUTO_IDX_MASK) { /* save probe resp ie index after auto-indexing */
*probe_idx = *((u16 *)pos);
len = sizeof(*pr_ie) - IEEE_MAX_IE_SIZE +
le16_to_cpu(pr_ie->ie_length);
pos += len;
} if (ar_ie && le16_to_cpu(ar_ie->ie_index) == MWIFIEX_AUTO_IDX_MASK) /* save assoc resp ie index after auto-indexing */
*assoc_idx = *((u16 *)pos);
kfree(ap_custom_ie); return ret;
}
/* This function checks if the vendor specified IE is present in passed buffer * and copies it to mwifiex_ie structure. * Function takes pointer to struct mwifiex_ie pointer as argument. * If the vendor specified IE is present then memory is allocated for * mwifiex_ie pointer and filled in with IE. Caller should take care of freeing * this memory.
*/ staticint mwifiex_update_vs_ie(const u8 *ies, int ies_len, struct mwifiex_ie **ie_ptr, u16 mask, unsignedint oui, u8 oui_type)
{ struct ieee_types_header *vs_ie; struct mwifiex_ie *ie = *ie_ptr; const u8 *vendor_ie;
vendor_ie = cfg80211_find_vendor_ie(oui, oui_type, ies, ies_len); if (vendor_ie) { if (!*ie_ptr) {
*ie_ptr = kzalloc(sizeof(struct mwifiex_ie),
GFP_KERNEL); if (!*ie_ptr) return -ENOMEM;
ie = *ie_ptr;
}
/* This function parses head and tail IEs, from cfg80211_beacon_data and sets * these IE to FW.
*/ staticint mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv, struct cfg80211_beacon_data *info)
{ struct mwifiex_ie *gen_ie; struct ieee_types_header *hdr; struct ieee80211_vendor_ie *vendorhdr;
u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0; int left_len, parsed_len = 0; unsignedint token_len; int err = 0;
if (!info->tail || !info->tail_len) return 0;
gen_ie = kzalloc(sizeof(*gen_ie), GFP_KERNEL); if (!gen_ie) return -ENOMEM;
left_len = info->tail_len;
/* Many IEs are generated in FW by parsing bss configuration. * Let's not add them here; else we may end up duplicating these IEs
*/ while (left_len > sizeof(struct ieee_types_header)) {
hdr = (void *)(info->tail + parsed_len);
token_len = hdr->len + sizeof(struct ieee_types_header); if (token_len > left_len) {
err = -EINVAL; goto out;
}
switch (hdr->element_id) { case WLAN_EID_SSID: case WLAN_EID_SUPP_RATES: case WLAN_EID_COUNTRY: case WLAN_EID_PWR_CONSTRAINT: case WLAN_EID_ERP_INFO: case WLAN_EID_EXT_SUPP_RATES: case WLAN_EID_HT_CAPABILITY: case WLAN_EID_HT_OPERATION: case WLAN_EID_VHT_CAPABILITY: case WLAN_EID_VHT_OPERATION: break; case WLAN_EID_VENDOR_SPECIFIC: /* Skip only Microsoft WMM IE */ if (cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
WLAN_OUI_TYPE_MICROSOFT_WMM,
(const u8 *)hdr,
token_len)) break;
fallthrough; default: if (ie_len + token_len > IEEE_MAX_IE_SIZE) {
err = -EINVAL; goto out;
}
memcpy(gen_ie->ie_buffer + ie_len, hdr, token_len);
ie_len += token_len; break;
}
left_len -= token_len;
parsed_len += token_len;
}
/* parse only WPA vendor IE from tail, WMM IE is configured by * bss_config command
*/
vendorhdr = (void *)cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT,
WLAN_OUI_TYPE_MICROSOFT_WPA,
info->tail, info->tail_len); if (vendorhdr) {
token_len = vendorhdr->len + sizeof(struct ieee_types_header); if (ie_len + token_len > IEEE_MAX_IE_SIZE) {
err = -EINVAL; goto out;
}
memcpy(gen_ie->ie_buffer + ie_len, vendorhdr, token_len);
ie_len += token_len;
}
/* This function parses different IEs-head & tail IEs, beacon IEs, * probe response IEs, association response IEs from cfg80211_ap_settings * function and sets these IE to FW.
*/ int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, struct cfg80211_beacon_data *info)
{ int ret;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.