[PATCH v3 2/3] hostap: set driver probe-response template
Arik Nemtsov
arik
Tue Nov 8 06:11:17 PST 2011
Configure a probe response template for drivers that support it. The
template is updated when the beacon is updated.
The probe response template is propagated to kernel via the set_ap()
callback.
Signed-off-by: Guy Eilam <guy at wizery.com>
Signed-off-by: Arik Nemtsov <arik at wizery.com>
---
v1->3:
- save offload-supported protocols bitmap in AP/P2P GO modes
- use set_ap() to propagate probe-response (and re-factor beacon
generating code so both happen in a common function)
- add warnings when unsupported protocols are offloaded
hostapd/main.c | 5 +-
src/ap/ap_list.c | 4 +-
src/ap/beacon.c | 364 ++++++++++++++++++++++++-------------
src/ap/beacon.h | 4 +-
src/ap/hostapd.c | 4 +-
src/ap/hostapd.h | 7 +
src/ap/ieee802_11.c | 6 +-
src/ap/ieee802_11_ht.c | 2 +-
src/ap/sta_info.c | 2 +-
src/ap/wps_hostapd.c | 2 +-
src/drivers/driver.h | 27 +++
wpa_supplicant/ap.c | 4 +-
wpa_supplicant/wpa_supplicant.c | 2 +
wpa_supplicant/wpa_supplicant_i.h | 7 +
14 files changed, 298 insertions(+), 142 deletions(-)
diff --git a/hostapd/main.c b/hostapd/main.c
index 99c137d..a781e44 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -303,8 +303,11 @@ static int hostapd_driver_init(struct hostapd_iface *iface)
}
if (hapd->driver->get_capa &&
- hapd->driver->get_capa(hapd->drv_priv, &capa) == 0)
+ hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) {
iface->drv_flags = capa.flags;
+ iface->probe_resp_offload_protocols =
+ capa.probe_resp_offload_protocols;
+ }
return 0;
}
diff --git a/src/ap/ap_list.c b/src/ap/ap_list.c
index 9b9fc9e..40ded63 100644
--- a/src/ap/ap_list.c
+++ b/src/ap/ap_list.c
@@ -326,7 +326,7 @@ void ap_list_process_beacon(struct hostapd_iface *iface,
#endif /* CONFIG_IEEE80211N */
if (set_beacon)
- ieee802_11_set_beacons(iface);
+ ieee802_11_set_beacons_and_probes(iface);
}
@@ -381,7 +381,7 @@ static void ap_list_timer(void *eloop_ctx, void *timeout_ctx)
}
if (set_beacon)
- ieee802_11_set_beacons(iface);
+ ieee802_11_set_beacons_and_probes(iface);
}
diff --git a/src/ap/beacon.c b/src/ap/beacon.c
index 4ba223c..f3b306a 100644
--- a/src/ap/beacon.c
+++ b/src/ap/beacon.c
@@ -186,18 +186,133 @@ static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len)
}
+#define MAX_PROBERESP_LEN 768
+
+int hostapd_alloc_probe_resp(struct hostapd_data *hapd, size_t resp_basic_len,
+ u8 **proberesp)
+{
+ size_t buflen = resp_basic_len;
+#ifdef CONFIG_WPS
+ if (hapd->wps_probe_resp_ie)
+ buflen += wpabuf_len(hapd->wps_probe_resp_ie);
+#endif /* CONFIG_WPS */
+#ifdef CONFIG_P2P
+ if (hapd->p2p_probe_resp_ie)
+ buflen += wpabuf_len(hapd->p2p_probe_resp_ie);
+#endif /* CONFIG_P2P */
+ *proberesp = os_zalloc(buflen);
+ if (*proberesp == NULL)
+ return -1;
+
+ return 0;
+}
+
+
+static size_t hostapd_gen_probe_resp(struct hostapd_data *hapd,
+ const struct ieee80211_mgmt *req,
+ struct ieee80211_mgmt *resp,
+ size_t resp_basic_len,
+ int is_p2p)
+{
+ u8 *pos, *epos;
+ struct sta_info *sta = NULL;
+
+ /* TODO: verify that supp_rates contains at least one matching rate
+ * with AP configuration */
+ epos = ((u8 *) resp) + resp_basic_len;
+
+ resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
+ WLAN_FC_STYPE_PROBE_RESP);
+ if (req)
+ os_memcpy(resp->da, req->sa, ETH_ALEN);
+ else
+ os_memset(resp->da, 0, sizeof(resp->da));
+ os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
+
+ os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
+ resp->u.probe_resp.beacon_int =
+ host_to_le16(hapd->iconf->beacon_int);
+
+ /* hardware or low-level driver will setup seq_ctrl and timestamp */
+ resp->u.probe_resp.capab_info =
+ host_to_le16(hostapd_own_capab_info(hapd, sta, 1));
+
+ pos = resp->u.probe_resp.variable;
+ *pos++ = WLAN_EID_SSID;
+ *pos++ = hapd->conf->ssid.ssid_len;
+ os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len);
+ pos += hapd->conf->ssid.ssid_len;
+
+ /* Supported rates */
+ pos = hostapd_eid_supp_rates(hapd, pos);
+
+ /* DS Params */
+ pos = hostapd_eid_ds_params(hapd, pos);
+
+ pos = hostapd_eid_country(hapd, pos, epos - pos);
+
+ /* ERP Information element */
+ pos = hostapd_eid_erp_info(hapd, pos);
+
+ /* Extended supported rates */
+ pos = hostapd_eid_ext_supp_rates(hapd, pos);
+
+ /* RSN, MDIE, WPA */
+ pos = hostapd_eid_wpa(hapd, pos, epos - pos);
+
+#ifdef CONFIG_IEEE80211N
+ pos = hostapd_eid_ht_capabilities(hapd, pos);
+ pos = hostapd_eid_ht_operation(hapd, pos);
+#endif /* CONFIG_IEEE80211N */
+
+ pos = hostapd_eid_ext_capab(hapd, pos);
+
+ pos = hostapd_eid_time_adv(hapd, pos);
+ pos = hostapd_eid_time_zone(hapd, pos);
+
+ pos = hostapd_eid_interworking(hapd, pos);
+ pos = hostapd_eid_adv_proto(hapd, pos);
+ pos = hostapd_eid_roaming_consortium(hapd, pos);
+
+ /* Wi-Fi Alliance WMM */
+ pos = hostapd_eid_wmm(hapd, pos);
+
+#ifdef CONFIG_WPS
+ if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) {
+ os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie),
+ wpabuf_len(hapd->wps_probe_resp_ie));
+ pos += wpabuf_len(hapd->wps_probe_resp_ie);
+ }
+#endif /* CONFIG_WPS */
+
+#ifdef CONFIG_P2P
+ if ((hapd->conf->p2p & P2P_ENABLED) && is_p2p &&
+ hapd->p2p_probe_resp_ie) {
+ os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie),
+ wpabuf_len(hapd->p2p_probe_resp_ie));
+ pos += wpabuf_len(hapd->p2p_probe_resp_ie);
+ }
+#endif /* CONFIG_P2P */
+#ifdef CONFIG_P2P_MANAGER
+ if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
+ P2P_MANAGE)
+ pos = hostapd_eid_p2p_manage(hapd, pos);
+#endif /* CONFIG_P2P_MANAGER */
+
+ return pos - (u8 *) resp;
+}
+
+
void handle_probe_req(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len)
{
struct ieee80211_mgmt *resp;
struct ieee802_11_elems elems;
char *ssid;
- u8 *pos, *epos;
const u8 *ie;
- size_t ssid_len, ie_len;
+ size_t ie_len;
struct sta_info *sta = NULL;
- size_t buflen;
- size_t i;
+ size_t i, resp_len;
ie = mgmt->u.probe_req.variable;
if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req))
@@ -220,7 +335,6 @@ void handle_probe_req(struct hostapd_data *hapd,
}
ssid = NULL;
- ssid_len = 0;
if ((!elems.ssid || !elems.supp_rates)) {
wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request "
@@ -267,7 +381,6 @@ void handle_probe_req(struct hostapd_data *hapd,
os_memcmp(elems.ssid, hapd->conf->ssid.ssid, elems.ssid_len) ==
0)) {
ssid = hapd->conf->ssid.ssid;
- ssid_len = hapd->conf->ssid.ssid_len;
if (sta)
sta->ssid_probe = &hapd->conf->ssid;
}
@@ -315,99 +428,13 @@ void handle_probe_req(struct hostapd_data *hapd,
}
#endif /* CONFIG_INTERWORKING */
- /* TODO: verify that supp_rates contains at least one matching rate
- * with AP configuration */
-#define MAX_PROBERESP_LEN 768
- buflen = MAX_PROBERESP_LEN;
-#ifdef CONFIG_WPS
- if (hapd->wps_probe_resp_ie)
- buflen += wpabuf_len(hapd->wps_probe_resp_ie);
-#endif /* CONFIG_WPS */
-#ifdef CONFIG_P2P
- if (hapd->p2p_probe_resp_ie)
- buflen += wpabuf_len(hapd->p2p_probe_resp_ie);
-#endif /* CONFIG_P2P */
- resp = os_zalloc(buflen);
- if (resp == NULL)
+ if (hostapd_alloc_probe_resp(hapd, MAX_PROBERESP_LEN, (u8 **)&resp) < 0)
return;
- epos = ((u8 *) resp) + MAX_PROBERESP_LEN;
-
- resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
- WLAN_FC_STYPE_PROBE_RESP);
- os_memcpy(resp->da, mgmt->sa, ETH_ALEN);
- os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
-
- os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
- resp->u.probe_resp.beacon_int =
- host_to_le16(hapd->iconf->beacon_int);
-
- /* hardware or low-level driver will setup seq_ctrl and timestamp */
- resp->u.probe_resp.capab_info =
- host_to_le16(hostapd_own_capab_info(hapd, sta, 1));
- pos = resp->u.probe_resp.variable;
- *pos++ = WLAN_EID_SSID;
- *pos++ = ssid_len;
- os_memcpy(pos, ssid, ssid_len);
- pos += ssid_len;
-
- /* Supported rates */
- pos = hostapd_eid_supp_rates(hapd, pos);
-
- /* DS Params */
- pos = hostapd_eid_ds_params(hapd, pos);
-
- pos = hostapd_eid_country(hapd, pos, epos - pos);
-
- /* ERP Information element */
- pos = hostapd_eid_erp_info(hapd, pos);
-
- /* Extended supported rates */
- pos = hostapd_eid_ext_supp_rates(hapd, pos);
-
- /* RSN, MDIE, WPA */
- pos = hostapd_eid_wpa(hapd, pos, epos - pos);
-
-#ifdef CONFIG_IEEE80211N
- pos = hostapd_eid_ht_capabilities(hapd, pos);
- pos = hostapd_eid_ht_operation(hapd, pos);
-#endif /* CONFIG_IEEE80211N */
-
- pos = hostapd_eid_ext_capab(hapd, pos);
-
- pos = hostapd_eid_time_adv(hapd, pos);
- pos = hostapd_eid_time_zone(hapd, pos);
-
- pos = hostapd_eid_interworking(hapd, pos);
- pos = hostapd_eid_adv_proto(hapd, pos);
- pos = hostapd_eid_roaming_consortium(hapd, pos);
-
- /* Wi-Fi Alliance WMM */
- pos = hostapd_eid_wmm(hapd, pos);
-
-#ifdef CONFIG_WPS
- if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) {
- os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie),
- wpabuf_len(hapd->wps_probe_resp_ie));
- pos += wpabuf_len(hapd->wps_probe_resp_ie);
- }
-#endif /* CONFIG_WPS */
-
-#ifdef CONFIG_P2P
- if ((hapd->conf->p2p & P2P_ENABLED) && elems.p2p &&
- hapd->p2p_probe_resp_ie) {
- os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie),
- wpabuf_len(hapd->p2p_probe_resp_ie));
- pos += wpabuf_len(hapd->p2p_probe_resp_ie);
- }
-#endif /* CONFIG_P2P */
-#ifdef CONFIG_P2P_MANAGER
- if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
- P2P_MANAGE)
- pos = hostapd_eid_p2p_manage(hapd, pos);
-#endif /* CONFIG_P2P_MANAGER */
+ resp_len = hostapd_gen_probe_resp(hapd, mgmt, resp, MAX_PROBERESP_LEN,
+ (int)elems.p2p);
- if (hostapd_drv_send_mlme(hapd, resp, pos - (u8 *) resp) < 0)
+ if (hostapd_drv_send_mlme(hapd, resp, resp_len) < 0)
perror("handle_probe_req: send");
os_free(resp);
@@ -417,28 +444,15 @@ void handle_probe_req(struct hostapd_data *hapd,
elems.ssid_len == 0 ? "broadcast" : "our");
}
-#endif /* NEED_AP_MLME */
-
-void ieee802_11_set_beacon(struct hostapd_data *hapd)
+static int hostapd_alloc_beacon(struct hostapd_data *hapd,
+ u8 **head, u8 **tail)
{
- struct ieee80211_mgmt *head = NULL;
- u8 *tail = NULL;
- size_t head_len = 0, tail_len = 0;
- struct wpa_driver_ap_params params;
- struct wpabuf *beacon, *proberesp, *assocresp;
-#ifdef NEED_AP_MLME
- u16 capab_info;
- u8 *pos, *tailpos;
-#endif /* NEED_AP_MLME */
-
- hapd->beacon_set_done = 1;
-
-#ifdef NEED_AP_MLME
+ size_t tail_len;
#define BEACON_HEAD_BUF_SIZE 256
#define BEACON_TAIL_BUF_SIZE 512
- head = os_zalloc(BEACON_HEAD_BUF_SIZE);
+ *head = os_zalloc(BEACON_HEAD_BUF_SIZE);
tail_len = BEACON_TAIL_BUF_SIZE;
#ifdef CONFIG_WPS
if (hapd->conf->wps_state && hapd->wps_beacon_ie)
@@ -448,14 +462,28 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
if (hapd->p2p_beacon_ie)
tail_len += wpabuf_len(hapd->p2p_beacon_ie);
#endif /* CONFIG_P2P */
- tailpos = tail = os_malloc(tail_len);
- if (head == NULL || tail == NULL) {
- wpa_printf(MSG_ERROR, "Failed to set beacon data");
- os_free(head);
- os_free(tail);
- return;
+ *tail = os_malloc(tail_len);
+ if (*head == NULL || *tail == NULL) {
+ wpa_printf(MSG_ERROR, "Failed to alloc beacon data");
+ os_free(*head);
+ os_free(*tail);
+ return -1;
}
+ return 0;
+}
+
+
+static void hostapd_gen_beacon(struct hostapd_data *hapd,
+ struct ieee80211_mgmt *head,
+ u8 *tail, size_t *head_len,
+ size_t *tail_len)
+{
+ u16 capab_info;
+ u8 *pos, *tailpos;
+
+ tailpos = tail;
+
head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
WLAN_FC_STYPE_BEACON);
head->duration = host_to_le16(0);
@@ -493,7 +521,7 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
/* DS Params */
pos = hostapd_eid_ds_params(hapd, pos);
- head_len = pos - (u8 *) head;
+ *head_len = pos - (u8 *) head;
tailpos = hostapd_eid_country(hapd, tailpos,
tail + BEACON_TAIL_BUF_SIZE - tailpos);
@@ -549,15 +577,30 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
tailpos = hostapd_eid_p2p_manage(hapd, tailpos);
#endif /* CONFIG_P2P_MANAGER */
- tail_len = tailpos > tail ? tailpos - tail : 0;
+ *tail_len = tailpos > tail ? tailpos - tail : 0;
+
+}
#endif /* NEED_AP_MLME */
+
+static void ieee802_11_set_ap(struct hostapd_data *hapd, const u8 *head,
+ size_t head_len, const u8 *tail, size_t tail_len,
+ const u8 *proberesp, size_t proberesp_len)
+{
+ struct wpa_driver_ap_params params;
+ struct wpabuf *beacon_ies = NULL, *proberesp_ies = NULL,
+ *assocresp_ies = NULL;
+
+ hapd->beacon_set_done = 1;
+
os_memset(¶ms, 0, sizeof(params));
params.head = (u8 *) head;
params.head_len = head_len;
params.tail = tail;
params.tail_len = tail_len;
+ params.proberesp = proberesp;
+ params.proberesp_len = proberesp_len;
params.dtim_period = hapd->conf->dtim_period;
params.beacon_int = hapd->iconf->beacon_int;
params.ssid = (u8 *) hapd->conf->ssid.ssid;
@@ -583,10 +626,12 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
params.hide_ssid = HIDDEN_SSID_ZERO_CONTENTS;
break;
}
- hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp);
- params.beacon_ies = beacon;
- params.proberesp_ies = proberesp;
- params.assocresp_ies = assocresp;
+
+ hostapd_build_ap_extra_ies(hapd, &beacon_ies, &proberesp_ies,
+ &assocresp_ies);
+ params.beacon_ies = beacon_ies;
+ params.proberesp_ies = proberesp_ies;
+ params.assocresp_ies = assocresp_ies;
params.isolate = hapd->conf->isolate;
#ifdef NEED_AP_MLME
params.cts_protect = !!(ieee802_11_erp_info(hapd) &
@@ -611,18 +656,81 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
params.access_network_type = hapd->conf->access_network_type;
if (hostapd_drv_set_ap(hapd, ¶ms))
wpa_printf(MSG_ERROR, "Failed to set beacon parameters");
- hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
+ hostapd_free_ap_extra_ies(hapd, beacon_ies, proberesp_ies,
+ assocresp_ies);
+
+}
+
+
+void ieee802_11_set_beacon_and_probe(struct hostapd_data *hapd)
+{
+ u8 *resp = NULL, *head = NULL, *tail = NULL;
+ size_t resp_len = 0, head_len = 0, tail_len = 0;
+
+ if (hostapd_alloc_beacon(hapd, &head, &tail) < 0)
+ goto fail;
+
+ hostapd_gen_beacon(hapd, (struct ieee80211_mgmt *)head, tail,
+ &head_len, &tail_len);
+
+#ifdef NEED_AP_MLME
+
+ /* check probe response offloading caps and print warnings */
+ if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD))
+ goto set;
+
+#ifdef CONFIG_WPS
+ if (hapd->conf->wps_state && hapd->wps_probe_resp_ie &&
+ (!(hapd->iface->probe_resp_offload_protocols &
+ WPA_DRIVER_PROBE_RESP_OFFLOAD_SUPPORT_WPS) ||
+ !(hapd->iface->probe_resp_offload_protocols &
+ WPA_DRIVER_PROBE_RESP_OFFLOAD_SUPPORT_WPS2)))
+ wpa_printf(MSG_WARNING, "Device is trying to offload WPS "
+ "probe-responses while not supporting WPS/WPS2 "
+ "probe-response offloading.");
+#endif /* CONFIG_WPS */
+
+#ifdef CONFIG_P2P
+ if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_probe_resp_ie &&
+ !(hapd->iface->probe_resp_offload_protocols &
+ WPA_DRIVER_PROBE_RESP_OFFLOAD_SUPPORT_P2P))
+ wpa_printf(MSG_WARNING, "Device is trying to offload P2P "
+ "probe-responses while not supporting P2P "
+ "probe-response offloading.");
+#endif /* CONFIG_P2P */
+
+ if (hapd->conf->interworking &&
+ !(hapd->iface->probe_resp_offload_protocols &
+ WPA_DRIVER_PROBE_RESP_OFFLOAD_SUPPORT_80211U))
+ wpa_printf(MSG_WARNING, "Device is trying to offload 802.11u "
+ "(interworking) probe-responses while not "
+ "supporting 802.11u probe-response offloading.");
+
+ if (hostapd_alloc_probe_resp(hapd, MAX_PROBERESP_LEN, &resp) < 0)
+ goto set;
+
+ /* we generate a probe-resp for the non-p2p case */
+ resp_len = hostapd_gen_probe_resp(hapd, NULL,
+ (struct ieee80211_mgmt *)resp,
+ MAX_PROBERESP_LEN, 0);
+#endif /* NEED_AP_MLME */
+
+set:
+ ieee802_11_set_ap(hapd, head, head_len, tail, tail_len, resp, resp_len);
+
+fail:
os_free(tail);
os_free(head);
+ os_free(resp);
}
-void ieee802_11_set_beacons(struct hostapd_iface *iface)
+void ieee802_11_set_beacons_and_probes(struct hostapd_iface *iface)
{
size_t i;
for (i = 0; i < iface->num_bss; i++)
- ieee802_11_set_beacon(iface->bss[i]);
+ ieee802_11_set_beacon_and_probe(iface->bss[i]);
}
#endif /* CONFIG_NATIVE_WINDOWS */
diff --git a/src/ap/beacon.h b/src/ap/beacon.h
index a944f5f..df687da 100644
--- a/src/ap/beacon.h
+++ b/src/ap/beacon.h
@@ -20,7 +20,7 @@ struct ieee80211_mgmt;
void handle_probe_req(struct hostapd_data *hapd,
const struct ieee80211_mgmt *mgmt, size_t len);
-void ieee802_11_set_beacon(struct hostapd_data *hapd);
-void ieee802_11_set_beacons(struct hostapd_iface *iface);
+void ieee802_11_set_beacon_and_probe(struct hostapd_data *hapd);
+void ieee802_11_set_beacons_and_probes(struct hostapd_iface *iface);
#endif /* BEACON_H */
diff --git a/src/ap/hostapd.c b/src/ap/hostapd.c
index e180a08..70b46da 100644
--- a/src/ap/hostapd.c
+++ b/src/ap/hostapd.c
@@ -81,7 +81,7 @@ static void hostapd_reload_bss(struct hostapd_data *hapd)
hostapd_set_generic_elem(hapd, (u8 *) "", 0);
}
- ieee802_11_set_beacon(hapd);
+ ieee802_11_set_beacon_and_probe(hapd);
hostapd_update_wps(hapd);
if (hapd->conf->ssid.ssid_set &&
@@ -629,7 +629,7 @@ static int hostapd_setup_bss(struct hostapd_data *hapd, int first)
return -1;
}
- ieee802_11_set_beacon(hapd);
+ ieee802_11_set_beacon_and_probe(hapd);
if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0)
return -1;
diff --git a/src/ap/hostapd.h b/src/ap/hostapd.h
index 5401e80..916e9f2 100644
--- a/src/ap/hostapd.h
+++ b/src/ap/hostapd.h
@@ -191,6 +191,13 @@ struct hostapd_iface {
struct ap_info *ap_iter_list;
unsigned int drv_flags;
+
+ /*
+ * A bitmap of supported protocols for probe response offload. See
+ * struct wpa_driver_capa in driver.h
+ */
+ unsigned int probe_resp_offload_protocols;
+
struct hostapd_hw_modes *hw_features;
int num_hw_features;
struct hostapd_hw_modes *current_mode;
diff --git a/src/ap/ieee802_11.c b/src/ap/ieee802_11.c
index 9fad335..d65f8d1 100644
--- a/src/ap/ieee802_11.c
+++ b/src/ap/ieee802_11.c
@@ -1018,7 +1018,7 @@ static void handle_assoc(struct hostapd_data *hapd,
sta->nonerp_set = 1;
hapd->iface->num_sta_non_erp++;
if (hapd->iface->num_sta_non_erp == 1)
- ieee802_11_set_beacons(hapd->iface);
+ ieee802_11_set_beacons_and_probes(hapd->iface);
}
if (!(sta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) &&
@@ -1028,7 +1028,7 @@ static void handle_assoc(struct hostapd_data *hapd,
if (hapd->iface->current_mode->mode ==
HOSTAPD_MODE_IEEE80211G &&
hapd->iface->num_sta_no_short_slot_time == 1)
- ieee802_11_set_beacons(hapd->iface);
+ ieee802_11_set_beacons_and_probes(hapd->iface);
}
if (sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)
@@ -1042,7 +1042,7 @@ static void handle_assoc(struct hostapd_data *hapd,
hapd->iface->num_sta_no_short_preamble++;
if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G
&& hapd->iface->num_sta_no_short_preamble == 1)
- ieee802_11_set_beacons(hapd->iface);
+ ieee802_11_set_beacons_and_probes(hapd->iface);
}
#ifdef CONFIG_IEEE80211N
diff --git a/src/ap/ieee802_11_ht.c b/src/ap/ieee802_11_ht.c
index 6c3696f..32d1e7c 100644
--- a/src/ap/ieee802_11_ht.c
+++ b/src/ap/ieee802_11_ht.c
@@ -236,7 +236,7 @@ void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta)
update_sta_no_ht(hapd, sta);
if (hostapd_ht_operation_update(hapd->iface) > 0)
- ieee802_11_set_beacons(hapd->iface);
+ ieee802_11_set_beacons_and_probes(hapd->iface);
}
diff --git a/src/ap/sta_info.c b/src/ap/sta_info.c
index dc689ba..df0682d 100644
--- a/src/ap/sta_info.c
+++ b/src/ap/sta_info.c
@@ -198,7 +198,7 @@ void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta)
#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */
if (set_beacon)
- ieee802_11_set_beacons(hapd->iface);
+ ieee802_11_set_beacons_and_probes(hapd->iface);
eloop_cancel_timeout(ap_handle_timer, hapd, sta);
eloop_cancel_timeout(ap_handle_session_timer, hapd, sta);
diff --git a/src/ap/wps_hostapd.c b/src/ap/wps_hostapd.c
index 671bc67..500e8a1 100644
--- a/src/ap/wps_hostapd.c
+++ b/src/ap/wps_hostapd.c
@@ -142,7 +142,7 @@ static int hostapd_wps_set_ie_cb(void *ctx, struct wpabuf *beacon_ie,
wpabuf_free(hapd->wps_probe_resp_ie);
hapd->wps_probe_resp_ie = probe_resp_ie;
if (hapd->beacon_set_done)
- ieee802_11_set_beacon(hapd);
+ ieee802_11_set_beacon_and_probe(hapd);
return hostapd_set_ap_wps_ie(hapd);
}
diff --git a/src/drivers/driver.h b/src/drivers/driver.h
index 2500c1e..477af6e 100644
--- a/src/drivers/driver.h
+++ b/src/drivers/driver.h
@@ -556,6 +556,19 @@ struct wpa_driver_ap_params {
int beacon_int;
/**
+ * proberesp - Probe response template
+ *
+ * This is used by drivers that reply to probe requests internally in
+ * AP mode and require the full probe response template.
+ */
+ const u8 *proberesp;
+
+ /**
+ * proberesp_len - Length of the proberesp buffer in octets
+ */
+ size_t proberesp_len;
+
+ /**
* ssid - The SSID to use in Beacon/Probe Response frames
*/
const u8 *ssid;
@@ -1444,6 +1457,20 @@ struct wpa_driver_ops {
int (*set_ap)(void *priv, struct wpa_driver_ap_params *params);
/**
+ * set_probe_resp - Set Probe Response frame template
+ * @priv: Private driver interface data
+ * @resp: Probe Response template
+ * @resp_len: Length of the resp buffer in octets
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is used to configure a Probe Response template for the
+ * driver in AP mode. The driver is responsible for building the full
+ * Probe Response frame by setting the destination address to that of
+ * the desired recipient.
+ */
+ int (*set_probe_resp)(void *priv, const u8 *resp, size_t resp_len);
+
+ /**
* hapd_init - Initialize driver interface (hostapd only)
* @hapd: Pointer to hostapd context
* @params: Configuration for the driver wrapper
diff --git a/wpa_supplicant/ap.c b/wpa_supplicant/ap.c
index e3d5433..1e17175 100644
--- a/wpa_supplicant/ap.c
+++ b/wpa_supplicant/ap.c
@@ -454,6 +454,8 @@ int wpa_supplicant_create_ap(struct wpa_supplicant *wpa_s,
return -1;
hapd_iface->owner = wpa_s;
hapd_iface->drv_flags = wpa_s->drv_flags;
+ hapd_iface->probe_resp_offload_protocols =
+ wpa_s->probe_resp_offload_protocols;
wpa_s->ap_iface->conf = conf = hostapd_config_defaults();
if (conf == NULL) {
@@ -900,7 +902,7 @@ int wpa_supplicant_ap_update_beacon(struct wpa_supplicant *wpa_s)
P2P_GROUP_FORMATION;
#endif /* CONFIG_P2P */
- ieee802_11_set_beacons(iface);
+ ieee802_11_set_beacons_and_probes(iface);
hapd = iface->bss[0];
hostapd_set_ap_wps_ie(hapd);
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 2b3140e..1bff61c 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -2325,6 +2325,8 @@ next_driver:
if (wpa_drv_get_capa(wpa_s, &capa) == 0) {
wpa_s->drv_capa_known = 1;
wpa_s->drv_flags = capa.flags;
+ wpa_s->probe_resp_offload_protocols =
+ capa.probe_resp_offload_protocols;
wpa_s->max_scan_ssids = capa.max_scan_ssids;
wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids;
wpa_s->sched_scan_supported = capa.sched_scan_supported;
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index fd04a7d..f661383 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -339,6 +339,13 @@ struct wpa_supplicant {
int scan_interval; /* time in sec between scans to find suitable AP */
unsigned int drv_flags;
+
+ /*
+ * A bitmap of supported protocols for probe response offload. See
+ * struct wpa_driver_capa in driver.h
+ */
+ unsigned int probe_resp_offload_protocols;
+
int max_scan_ssids;
int max_sched_scan_ssids;
int sched_scan_supported;
--
1.7.5.4
More information about the Hostap
mailing list