|
@@ -3102,6 +3102,62 @@ static void wl12xx_remove_vendor_ie(struct sk_buff *skb,
|
|
|
skb_trim(skb, skb->len - len);
|
|
|
}
|
|
|
|
|
|
+static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl,
|
|
|
+ u8 *probe_rsp_data,
|
|
|
+ size_t probe_rsp_len,
|
|
|
+ u32 rates)
|
|
|
+{
|
|
|
+ struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
|
|
|
+ u8 probe_rsp_templ[WL1271_CMD_TEMPL_MAX_SIZE];
|
|
|
+ int ssid_ie_offset, ie_offset, templ_len;
|
|
|
+ const u8 *ptr;
|
|
|
+
|
|
|
+ /* no need to change probe response if the SSID is set correctly */
|
|
|
+ if (wl->ssid_len > 0)
|
|
|
+ return wl1271_cmd_template_set(wl,
|
|
|
+ CMD_TEMPL_AP_PROBE_RESPONSE,
|
|
|
+ probe_rsp_data,
|
|
|
+ probe_rsp_len, 0,
|
|
|
+ rates);
|
|
|
+
|
|
|
+ if (probe_rsp_len + bss_conf->ssid_len > WL1271_CMD_TEMPL_MAX_SIZE) {
|
|
|
+ wl1271_error("probe_rsp template too big");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* start searching from IE offset */
|
|
|
+ ie_offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
|
|
|
+
|
|
|
+ ptr = cfg80211_find_ie(WLAN_EID_SSID, probe_rsp_data + ie_offset,
|
|
|
+ probe_rsp_len - ie_offset);
|
|
|
+ if (!ptr) {
|
|
|
+ wl1271_error("No SSID in beacon!");
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ ssid_ie_offset = ptr - probe_rsp_data;
|
|
|
+ ptr += (ptr[1] + 2);
|
|
|
+
|
|
|
+ memcpy(probe_rsp_templ, probe_rsp_data, ssid_ie_offset);
|
|
|
+
|
|
|
+ /* insert SSID from bss_conf */
|
|
|
+ probe_rsp_templ[ssid_ie_offset] = WLAN_EID_SSID;
|
|
|
+ probe_rsp_templ[ssid_ie_offset + 1] = bss_conf->ssid_len;
|
|
|
+ memcpy(probe_rsp_templ + ssid_ie_offset + 2,
|
|
|
+ bss_conf->ssid, bss_conf->ssid_len);
|
|
|
+ templ_len = ssid_ie_offset + 2 + bss_conf->ssid_len;
|
|
|
+
|
|
|
+ memcpy(probe_rsp_templ + ssid_ie_offset + 2 + bss_conf->ssid_len,
|
|
|
+ ptr, probe_rsp_len - (ptr - probe_rsp_data));
|
|
|
+ templ_len += probe_rsp_len - (ptr - probe_rsp_data);
|
|
|
+
|
|
|
+ return wl1271_cmd_template_set(wl,
|
|
|
+ CMD_TEMPL_AP_PROBE_RESPONSE,
|
|
|
+ probe_rsp_templ,
|
|
|
+ templ_len, 0,
|
|
|
+ rates);
|
|
|
+}
|
|
|
+
|
|
|
static int wl1271_bss_erp_info_changed(struct wl1271 *wl,
|
|
|
struct ieee80211_bss_conf *bss_conf,
|
|
|
u32 changed)
|
|
@@ -3201,14 +3257,17 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
|
|
|
hdr = (struct ieee80211_hdr *) beacon->data;
|
|
|
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
|
|
|
IEEE80211_STYPE_PROBE_RESP);
|
|
|
-
|
|
|
- tmpl_id = is_ap ? CMD_TEMPL_AP_PROBE_RESPONSE :
|
|
|
- CMD_TEMPL_PROBE_RESPONSE;
|
|
|
- ret = wl1271_cmd_template_set(wl,
|
|
|
- tmpl_id,
|
|
|
- beacon->data,
|
|
|
- beacon->len, 0,
|
|
|
- wl1271_tx_min_rate_get(wl));
|
|
|
+ if (is_ap)
|
|
|
+ ret = wl1271_ap_set_probe_resp_tmpl(wl,
|
|
|
+ beacon->data,
|
|
|
+ beacon->len,
|
|
|
+ wl1271_tx_min_rate_get(wl));
|
|
|
+ else
|
|
|
+ ret = wl1271_cmd_template_set(wl,
|
|
|
+ CMD_TEMPL_PROBE_RESPONSE,
|
|
|
+ beacon->data,
|
|
|
+ beacon->len, 0,
|
|
|
+ wl1271_tx_min_rate_get(wl));
|
|
|
dev_kfree_skb(beacon);
|
|
|
if (ret < 0)
|
|
|
goto out;
|