Provide extra IEs for AP mode management frames with set_ap
Drivers that build Beacon, Probe Response, and (Re)Association Response frames can use this information to and WPS and P2P IE when needed.
This commit is contained in:
parent
97a7a0b504
commit
fb91db5639
5 changed files with 114 additions and 43 deletions
|
@ -41,49 +41,47 @@ u32 hostapd_sta_flags_to_drv(u32 flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
|
int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
|
||||||
|
struct wpabuf **beacon,
|
||||||
|
struct wpabuf **proberesp,
|
||||||
|
struct wpabuf **assocresp)
|
||||||
{
|
{
|
||||||
struct wpabuf *beacon, *proberesp, *assocresp = NULL;
|
*beacon = hapd->wps_beacon_ie;
|
||||||
int ret;
|
*proberesp = hapd->wps_probe_resp_ie;
|
||||||
|
*assocresp = NULL;
|
||||||
if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
beacon = hapd->wps_beacon_ie;
|
|
||||||
proberesp = hapd->wps_probe_resp_ie;
|
|
||||||
|
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
if (hapd->wps_beacon_ie == NULL && hapd->p2p_beacon_ie == NULL)
|
if (hapd->wps_beacon_ie == NULL && hapd->p2p_beacon_ie == NULL)
|
||||||
beacon = NULL;
|
*beacon = NULL;
|
||||||
else {
|
else {
|
||||||
beacon = wpabuf_alloc((hapd->wps_beacon_ie ?
|
*beacon = wpabuf_alloc((hapd->wps_beacon_ie ?
|
||||||
wpabuf_len(hapd->wps_beacon_ie) : 0) +
|
wpabuf_len(hapd->wps_beacon_ie) : 0) +
|
||||||
(hapd->p2p_beacon_ie ?
|
(hapd->p2p_beacon_ie ?
|
||||||
wpabuf_len(hapd->p2p_beacon_ie) : 0));
|
wpabuf_len(hapd->p2p_beacon_ie) : 0));
|
||||||
if (beacon == NULL)
|
if (*beacon == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
if (hapd->wps_beacon_ie)
|
if (hapd->wps_beacon_ie)
|
||||||
wpabuf_put_buf(beacon, hapd->wps_beacon_ie);
|
wpabuf_put_buf(*beacon, hapd->wps_beacon_ie);
|
||||||
if (hapd->p2p_beacon_ie)
|
if (hapd->p2p_beacon_ie)
|
||||||
wpabuf_put_buf(beacon, hapd->p2p_beacon_ie);
|
wpabuf_put_buf(*beacon, hapd->p2p_beacon_ie);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hapd->wps_probe_resp_ie == NULL && hapd->p2p_probe_resp_ie == NULL)
|
if (hapd->wps_probe_resp_ie == NULL && hapd->p2p_probe_resp_ie == NULL)
|
||||||
proberesp = NULL;
|
*proberesp = NULL;
|
||||||
else {
|
else {
|
||||||
proberesp = wpabuf_alloc(
|
*proberesp = wpabuf_alloc(
|
||||||
(hapd->wps_probe_resp_ie ?
|
(hapd->wps_probe_resp_ie ?
|
||||||
wpabuf_len(hapd->wps_probe_resp_ie) : 0) +
|
wpabuf_len(hapd->wps_probe_resp_ie) : 0) +
|
||||||
(hapd->p2p_probe_resp_ie ?
|
(hapd->p2p_probe_resp_ie ?
|
||||||
wpabuf_len(hapd->p2p_probe_resp_ie) : 0));
|
wpabuf_len(hapd->p2p_probe_resp_ie) : 0));
|
||||||
if (proberesp == NULL) {
|
if (*proberesp == NULL) {
|
||||||
wpabuf_free(beacon);
|
wpabuf_free(*beacon);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (hapd->wps_probe_resp_ie)
|
if (hapd->wps_probe_resp_ie)
|
||||||
wpabuf_put_buf(proberesp, hapd->wps_probe_resp_ie);
|
wpabuf_put_buf(*proberesp, hapd->wps_probe_resp_ie);
|
||||||
if (hapd->p2p_probe_resp_ie)
|
if (hapd->p2p_probe_resp_ie)
|
||||||
wpabuf_put_buf(proberesp, hapd->p2p_probe_resp_ie);
|
wpabuf_put_buf(*proberesp, hapd->p2p_probe_resp_ie);
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_P2P */
|
#endif /* CONFIG_P2P */
|
||||||
|
|
||||||
|
@ -91,67 +89,91 @@ int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
|
||||||
if (hapd->conf->p2p & P2P_MANAGE) {
|
if (hapd->conf->p2p & P2P_MANAGE) {
|
||||||
struct wpabuf *a;
|
struct wpabuf *a;
|
||||||
|
|
||||||
a = wpabuf_alloc(100 + (beacon ? wpabuf_len(beacon) : 0));
|
a = wpabuf_alloc(100 + (*beacon ? wpabuf_len(*beacon) : 0));
|
||||||
if (a) {
|
if (a) {
|
||||||
u8 *start, *p;
|
u8 *start, *p;
|
||||||
if (beacon)
|
if (*beacon)
|
||||||
wpabuf_put_buf(a, beacon);
|
wpabuf_put_buf(a, *beacon);
|
||||||
if (beacon != hapd->wps_beacon_ie)
|
if (*beacon != hapd->wps_beacon_ie)
|
||||||
wpabuf_free(beacon);
|
wpabuf_free(*beacon);
|
||||||
start = wpabuf_put(a, 0);
|
start = wpabuf_put(a, 0);
|
||||||
p = hostapd_eid_p2p_manage(hapd, start);
|
p = hostapd_eid_p2p_manage(hapd, start);
|
||||||
wpabuf_put(a, p - start);
|
wpabuf_put(a, p - start);
|
||||||
beacon = a;
|
*beacon = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
a = wpabuf_alloc(100 + (proberesp ? wpabuf_len(proberesp) :
|
a = wpabuf_alloc(100 + (*proberesp ? wpabuf_len(*proberesp) :
|
||||||
0));
|
0));
|
||||||
if (a) {
|
if (a) {
|
||||||
u8 *start, *p;
|
u8 *start, *p;
|
||||||
if (proberesp)
|
if (*proberesp)
|
||||||
wpabuf_put_buf(a, proberesp);
|
wpabuf_put_buf(a, *proberesp);
|
||||||
if (proberesp != hapd->wps_probe_resp_ie)
|
if (*proberesp != hapd->wps_probe_resp_ie)
|
||||||
wpabuf_free(proberesp);
|
wpabuf_free(*proberesp);
|
||||||
start = wpabuf_put(a, 0);
|
start = wpabuf_put(a, 0);
|
||||||
p = hostapd_eid_p2p_manage(hapd, start);
|
p = hostapd_eid_p2p_manage(hapd, start);
|
||||||
wpabuf_put(a, p - start);
|
wpabuf_put(a, p - start);
|
||||||
proberesp = a;
|
*proberesp = a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_P2P_MANAGER */
|
#endif /* CONFIG_P2P_MANAGER */
|
||||||
|
|
||||||
#ifdef CONFIG_WPS2
|
#ifdef CONFIG_WPS2
|
||||||
if (hapd->conf->wps_state)
|
if (hapd->conf->wps_state)
|
||||||
assocresp = wps_build_assoc_resp_ie();
|
*assocresp = wps_build_assoc_resp_ie();
|
||||||
#endif /* CONFIG_WPS2 */
|
#endif /* CONFIG_WPS2 */
|
||||||
|
|
||||||
#ifdef CONFIG_P2P_MANAGER
|
#ifdef CONFIG_P2P_MANAGER
|
||||||
if (hapd->conf->p2p & P2P_MANAGE) {
|
if (hapd->conf->p2p & P2P_MANAGE) {
|
||||||
struct wpabuf *a;
|
struct wpabuf *a;
|
||||||
a = wpabuf_alloc(100 + (assocresp ? wpabuf_len(assocresp) :
|
a = wpabuf_alloc(100 + (*assocresp ? wpabuf_len(*assocresp) :
|
||||||
0));
|
0));
|
||||||
if (a) {
|
if (a) {
|
||||||
u8 *start, *p;
|
u8 *start, *p;
|
||||||
start = wpabuf_put(a, 0);
|
start = wpabuf_put(a, 0);
|
||||||
p = hostapd_eid_p2p_manage(hapd, start);
|
p = hostapd_eid_p2p_manage(hapd, start);
|
||||||
wpabuf_put(a, p - start);
|
wpabuf_put(a, p - start);
|
||||||
if (assocresp) {
|
if (*assocresp) {
|
||||||
wpabuf_put_buf(a, assocresp);
|
wpabuf_put_buf(a, *assocresp);
|
||||||
wpabuf_free(assocresp);
|
wpabuf_free(*assocresp);
|
||||||
}
|
}
|
||||||
assocresp = a;
|
*assocresp = a;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_P2P_MANAGER */
|
#endif /* CONFIG_P2P_MANAGER */
|
||||||
|
|
||||||
ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp,
|
return 0;
|
||||||
assocresp);
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void hostapd_free_ap_extra_ies(struct hostapd_data *hapd, struct wpabuf *beacon,
|
||||||
|
struct wpabuf *proberesp,
|
||||||
|
struct wpabuf *assocresp)
|
||||||
|
{
|
||||||
if (beacon != hapd->wps_beacon_ie)
|
if (beacon != hapd->wps_beacon_ie)
|
||||||
wpabuf_free(beacon);
|
wpabuf_free(beacon);
|
||||||
if (proberesp != hapd->wps_probe_resp_ie)
|
if (proberesp != hapd->wps_probe_resp_ie)
|
||||||
wpabuf_free(proberesp);
|
wpabuf_free(proberesp);
|
||||||
wpabuf_free(assocresp);
|
wpabuf_free(assocresp);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int hostapd_set_ap_wps_ie(struct hostapd_data *hapd)
|
||||||
|
{
|
||||||
|
struct wpabuf *beacon, *proberesp, *assocresp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) <
|
||||||
|
0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp,
|
||||||
|
assocresp);
|
||||||
|
|
||||||
|
hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,6 +21,13 @@ struct wpa_driver_scan_params;
|
||||||
struct ieee80211_ht_capabilities;
|
struct ieee80211_ht_capabilities;
|
||||||
|
|
||||||
u32 hostapd_sta_flags_to_drv(u32 flags);
|
u32 hostapd_sta_flags_to_drv(u32 flags);
|
||||||
|
int hostapd_build_ap_extra_ies(struct hostapd_data *hapd,
|
||||||
|
struct wpabuf **beacon,
|
||||||
|
struct wpabuf **proberesp,
|
||||||
|
struct wpabuf **assocresp);
|
||||||
|
void hostapd_free_ap_extra_ies(struct hostapd_data *hapd, struct wpabuf *beacon,
|
||||||
|
struct wpabuf *proberesp,
|
||||||
|
struct wpabuf *assocresp);
|
||||||
int hostapd_set_ap_wps_ie(struct hostapd_data *hapd);
|
int hostapd_set_ap_wps_ie(struct hostapd_data *hapd);
|
||||||
int hostapd_set_authorized(struct hostapd_data *hapd,
|
int hostapd_set_authorized(struct hostapd_data *hapd,
|
||||||
struct sta_info *sta, int authorized);
|
struct sta_info *sta, int authorized);
|
||||||
|
|
|
@ -399,6 +399,7 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
|
||||||
u16 capab_info;
|
u16 capab_info;
|
||||||
size_t head_len, tail_len;
|
size_t head_len, tail_len;
|
||||||
struct wpa_driver_ap_params params;
|
struct wpa_driver_ap_params params;
|
||||||
|
struct wpabuf *beacon, *proberesp, *assocresp;
|
||||||
|
|
||||||
#ifdef CONFIG_P2P
|
#ifdef CONFIG_P2P
|
||||||
if ((hapd->conf->p2p & (P2P_ENABLED | P2P_GROUP_OWNER)) == P2P_ENABLED)
|
if ((hapd->conf->p2p & (P2P_ENABLED | P2P_GROUP_OWNER)) == P2P_ENABLED)
|
||||||
|
@ -541,8 +542,13 @@ void ieee802_11_set_beacon(struct hostapd_data *hapd)
|
||||||
params.hide_ssid = HIDDEN_SSID_ZERO_CONTENTS;
|
params.hide_ssid = HIDDEN_SSID_ZERO_CONTENTS;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp);
|
||||||
|
params.beacon_ies = beacon;
|
||||||
|
params.proberesp_ies = proberesp;
|
||||||
|
params.assocresp_ies = assocresp;
|
||||||
if (hostapd_drv_set_ap(hapd, ¶ms))
|
if (hostapd_drv_set_ap(hapd, ¶ms))
|
||||||
wpa_printf(MSG_ERROR, "Failed to set beacon parameters");
|
wpa_printf(MSG_ERROR, "Failed to set beacon parameters");
|
||||||
|
hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
|
||||||
|
|
||||||
os_free(tail);
|
os_free(tail);
|
||||||
os_free(head);
|
os_free(head);
|
||||||
|
|
|
@ -581,6 +581,27 @@ struct wpa_driver_ap_params {
|
||||||
* privacy - Whether privacy is used in the BSS
|
* privacy - Whether privacy is used in the BSS
|
||||||
*/
|
*/
|
||||||
int privacy;
|
int privacy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* beacon_ies - WPS/P2P IE(s) for Beacon frames
|
||||||
|
*
|
||||||
|
* This is used to add IEs like WPS IE and P2P IE by drivers that do not
|
||||||
|
* use the full Beacon template.
|
||||||
|
*/
|
||||||
|
const struct wpabuf *beacon_ies;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* proberesp_ies - P2P/WPS IE(s) for Probe Response frames
|
||||||
|
*
|
||||||
|
* This is used to add IEs like WPS IE and P2P IE by drivers that
|
||||||
|
* reply to Probe Request frames internally.
|
||||||
|
*/
|
||||||
|
const struct wpabuf *proberesp_ies;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* assocresp_ies - WPS IE(s) for (Re)Association Response frames
|
||||||
|
*/
|
||||||
|
const struct wpabuf *assocresp_ies;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -3929,6 +3929,21 @@ static int wpa_driver_nl80211_set_ap(void *priv,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (params->beacon_ies) {
|
||||||
|
NLA_PUT(msg, NL80211_ATTR_IE, wpabuf_len(params->beacon_ies),
|
||||||
|
wpabuf_head(params->beacon_ies));
|
||||||
|
}
|
||||||
|
if (params->proberesp_ies) {
|
||||||
|
NLA_PUT(msg, NL80211_ATTR_IE_PROBE_RESP,
|
||||||
|
wpabuf_len(params->proberesp_ies),
|
||||||
|
wpabuf_head(params->proberesp_ies));
|
||||||
|
}
|
||||||
|
if (params->assocresp_ies) {
|
||||||
|
NLA_PUT(msg, NL80211_ATTR_IE_ASSOC_RESP,
|
||||||
|
wpabuf_len(params->assocresp_ies),
|
||||||
|
wpabuf_head(params->assocresp_ies));
|
||||||
|
}
|
||||||
|
|
||||||
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
ret = send_and_recv_msgs(drv, msg, NULL, NULL);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",
|
wpa_printf(MSG_DEBUG, "nl80211: Beacon set failed: %d (%s)",
|
||||||
|
|
Loading…
Reference in a new issue