13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright (c) 2002-2004, Instant802 Networks, Inc.
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright (c) 2005-2006, Devicescape Software, Inc.
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright (c) 2008-2012, Jouni Malinen <j@w1.fi>
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * This software may be distributed under the terms of the BSD license.
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See README for more details.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry */
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "utils/includes.h"
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifndef CONFIG_NATIVE_WINDOWS
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "utils/common.h"
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "common/ieee802_11_defs.h"
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "common/ieee802_11_common.h"
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "wps/wps_defs.h"
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "p2p/p2p.h"
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "hostapd.h"
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "ieee802_11.h"
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "wpa_auth.h"
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "wmm.h"
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "ap_config.h"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "sta_info.h"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "p2p_hostapd.h"
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "ap_drv_ops.h"
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "beacon.h"
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "hs20.h"
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "dfs.h"
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef NEED_AP_MLME
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic u8 * hostapd_eid_bss_load(struct hostapd_data *hapd, u8 *eid, size_t len)
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_TESTING_OPTIONS
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->conf->bss_load_test_set) {
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (2 + 5 > len)
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return eid;
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*eid++ = WLAN_EID_BSS_LOAD;
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*eid++ = 5;
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os_memcpy(eid, hapd->conf->bss_load_test, 5);
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		eid += 5;
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_TESTING_OPTIONS */
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return eid;
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic u8 ieee802_11_erp_info(struct hostapd_data *hapd)
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	u8 erp = 0;
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->iface->current_mode == NULL ||
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return 0;
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->iface->olbc)
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		erp |= ERP_INFO_USE_PROTECTION;
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->iface->num_sta_non_erp > 0) {
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		erp |= ERP_INFO_NON_ERP_PRESENT |
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ERP_INFO_USE_PROTECTION;
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->iface->num_sta_no_short_preamble > 0 ||
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    hapd->iconf->preamble == LONG_PREAMBLE)
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		erp |= ERP_INFO_BARKER_PREAMBLE_MODE;
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return erp;
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic u8 * hostapd_eid_ds_params(struct hostapd_data *hapd, u8 *eid)
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*eid++ = WLAN_EID_DS_PARAMS;
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*eid++ = 1;
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*eid++ = hapd->iconf->channel;
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return eid;
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic u8 * hostapd_eid_erp_info(struct hostapd_data *hapd, u8 *eid)
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->iface->current_mode == NULL ||
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G)
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return eid;
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Set NonERP_present and use_protection bits if there
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * are any associated NonERP stations. */
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* TODO: use_protection bit can be set to zero even if
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * there are NonERP stations present. This optimization
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * might be useful if NonERP stations are "quiet".
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * See 802.11g/D6 E-1 for recommended practice.
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * In addition, Non ERP present might be set, if AP detects Non ERP
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * operation on other APs. */
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Add ERP Information element */
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*eid++ = WLAN_EID_ERP_INFO;
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*eid++ = 1;
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*eid++ = ieee802_11_erp_info(hapd);
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return eid;
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic u8 * hostapd_eid_pwr_constraint(struct hostapd_data *hapd, u8 *eid)
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	u8 *pos = eid;
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	u8 local_pwr_constraint = 0;
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int dfs;
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->iface->current_mode == NULL ||
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A)
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return eid;
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Let host drivers add this IE if DFS support is offloaded */
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return eid;
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/*
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * There is no DFS support and power constraint was not directly
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * requested by config option.
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 */
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!hapd->iconf->ieee80211h &&
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    hapd->iconf->local_pwr_constraint == -1)
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return eid;
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Check if DFS is required by regulatory. */
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dfs = hostapd_is_dfs_required(hapd->iface);
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (dfs < 0) {
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		wpa_printf(MSG_WARNING, "Failed to check if DFS is required; ret=%d",
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   dfs);
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dfs = 0;
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (dfs == 0 && hapd->iconf->local_pwr_constraint == -1)
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return eid;
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/*
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * ieee80211h (DFS) is enabled so Power Constraint element shall
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * be added when running on DFS channel whenever local_pwr_constraint
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * is configured or not. In order to meet regulations when TPC is not
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * implemented using a transmit power that is below the legal maximum
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * (including any mitigation factor) should help. In this case,
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * indicate 3 dB below maximum allowed transmit power.
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 */
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->iconf->local_pwr_constraint == -1)
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		local_pwr_constraint = 3;
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/*
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * A STA that is not an AP shall use a transmit power less than or
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * equal to the local maximum transmit power level for the channel.
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * The local maximum transmit power can be calculated from the formula:
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * local max TX pwr = max TX pwr - local pwr constraint
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * Where max TX pwr is maximum transmit power level specified for
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * channel in Country element and local pwr constraint is specified
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * for channel in this Power Constraint element.
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 */
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Element ID */
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*pos++ = WLAN_EID_PWR_CONSTRAINT;
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Length */
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*pos++ = 1;
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Local Power Constraint */
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (local_pwr_constraint)
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*pos++ = local_pwr_constraint;
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*pos++ = hapd->iconf->local_pwr_constraint;
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return pos;
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic u8 * hostapd_eid_country_add(u8 *pos, u8 *end, int chan_spacing,
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				    struct hostapd_channel_data *start,
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				    struct hostapd_channel_data *prev)
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (end - pos < 3)
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return pos;
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* first channel number */
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*pos++ = start->chan;
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* number of channels */
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*pos++ = (prev->chan - start->chan) / chan_spacing + 1;
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* maximum transmit power level */
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*pos++ = start->max_tx_power;
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return pos;
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid,
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int max_len)
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	u8 *pos = eid;
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	u8 *end = eid + max_len;
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int i;
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct hostapd_hw_modes *mode;
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct hostapd_channel_data *start, *prev;
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int chan_spacing = 1;
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!hapd->iconf->ieee80211d || max_len < 6 ||
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    hapd->iface->current_mode == NULL)
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return eid;
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*pos++ = WLAN_EID_COUNTRY;
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos++; /* length will be set later */
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	os_memcpy(pos, hapd->iconf->country, 3); /* e.g., 'US ' */
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos += 3;
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	mode = hapd->iface->current_mode;
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (mode->mode == HOSTAPD_MODE_IEEE80211A)
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		chan_spacing = 4;
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	start = prev = NULL;
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (i = 0; i < mode->num_channels; i++) {
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		struct hostapd_channel_data *chan = &mode->channels[i];
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (chan->flag & HOSTAPD_CHAN_DISABLED)
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue;
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (start && prev &&
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		    prev->chan + chan_spacing == chan->chan &&
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		    start->max_tx_power == chan->max_tx_power) {
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			prev = chan;
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			continue; /* can use same entry */
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (start && prev) {
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			pos = hostapd_eid_country_add(pos, end, chan_spacing,
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						      start, prev);
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			start = NULL;
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Start new group */
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		start = prev = chan;
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (start) {
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pos = hostapd_eid_country_add(pos, end, chan_spacing,
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					      start, prev);
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if ((pos - eid) & 1) {
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (end - pos < 1)
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return eid;
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*pos++ = 0; /* pad for 16-bit alignment */
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	eid[1] = (pos - eid) - 2;
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return pos;
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len)
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const u8 *ie;
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	size_t ielen;
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen);
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (ie == NULL || ielen > len)
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return eid;
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	os_memcpy(eid, ie, ielen);
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return eid + ielen;
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic u8 * hostapd_eid_csa(struct hostapd_data *hapd, u8 *eid)
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	u8 chan;
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!hapd->cs_freq_params.freq)
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return eid;
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (ieee80211_freq_to_chan(hapd->cs_freq_params.freq, &chan) ==
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    NUM_HOSTAPD_MODES)
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return eid;
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*eid++ = WLAN_EID_CHANNEL_SWITCH;
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*eid++ = 3;
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*eid++ = hapd->cs_block_tx;
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*eid++ = chan;
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*eid++ = hapd->cs_count;
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return eid;
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid)
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	u8 sec_ch;
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!hapd->cs_freq_params.sec_channel_offset)
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return eid;
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->cs_freq_params.sec_channel_offset == -1)
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW;
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else if (hapd->cs_freq_params.sec_channel_offset == 1)
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE;
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return eid;
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*eid++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET;
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*eid++ = 1;
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*eid++ = sec_ch;
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return eid;
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic u8 * hostapd_add_csa_elems(struct hostapd_data *hapd, u8 *pos,
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				  u8 *start, unsigned int *csa_counter_off)
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	u8 *old_pos = pos;
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!csa_counter_off)
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return pos;
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*csa_counter_off = 0;
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_csa(hapd, pos);
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (pos != old_pos) {
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* save an offset to the counter - should be last byte */
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*csa_counter_off = pos - start - 1;
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pos = hostapd_eid_secondary_channel(hapd, pos);
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return pos;
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd,
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   struct sta_info *sta,
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   const struct ieee80211_mgmt *req,
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   int is_p2p, size_t *resp_len)
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct ieee80211_mgmt *resp;
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	u8 *pos, *epos;
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	size_t buflen;
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define MAX_PROBERESP_LEN 768
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	buflen = MAX_PROBERESP_LEN;
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_WPS
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->wps_probe_resp_ie)
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buflen += wpabuf_len(hapd->wps_probe_resp_ie);
3463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_WPS */
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_P2P
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->p2p_probe_resp_ie)
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buflen += wpabuf_len(hapd->p2p_probe_resp_ie);
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_P2P */
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->conf->vendor_elements)
3523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		buflen += wpabuf_len(hapd->conf->vendor_elements);
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	resp = os_zalloc(buflen);
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (resp == NULL)
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return NULL;
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	epos = ((u8 *) resp) + MAX_PROBERESP_LEN;
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					   WLAN_FC_STYPE_PROBE_RESP);
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (req)
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os_memcpy(resp->da, req->sa, ETH_ALEN);
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN);
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN);
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	resp->u.probe_resp.beacon_int =
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		host_to_le16(hapd->iconf->beacon_int);
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* hardware or low-level driver will setup seq_ctrl and timestamp */
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	resp->u.probe_resp.capab_info =
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		host_to_le16(hostapd_own_capab_info(hapd, sta, 1));
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = resp->u.probe_resp.variable;
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*pos++ = WLAN_EID_SSID;
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*pos++ = hapd->conf->ssid.ssid_len;
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len);
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos += hapd->conf->ssid.ssid_len;
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Supported rates */
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_supp_rates(hapd, pos);
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* DS Params */
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_ds_params(hapd, pos);
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_country(hapd, pos, epos - pos);
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Power Constraint element */
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_pwr_constraint(hapd, pos);
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* ERP Information element */
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_erp_info(hapd, pos);
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Extended supported rates */
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_ext_supp_rates(hapd, pos);
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* RSN, MDIE, WPA */
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_wpa(hapd, pos, epos - pos);
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_bss_load(hapd, pos, epos - pos);
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_IEEE80211N
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_ht_capabilities(hapd, pos);
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_ht_operation(hapd, pos);
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_IEEE80211N */
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_ext_capab(hapd, pos);
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_time_adv(hapd, pos);
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_time_zone(hapd, pos);
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_interworking(hapd, pos);
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_adv_proto(hapd, pos);
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_roaming_consortium(hapd, pos);
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_add_csa_elems(hapd, pos, (u8 *)resp,
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				    &hapd->cs_c_off_proberesp);
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_IEEE80211AC
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_vht_capabilities(hapd, pos);
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_vht_operation(hapd, pos);
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_IEEE80211AC */
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Wi-Fi Alliance WMM */
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_wmm(hapd, pos);
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_WPS
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) {
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie),
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  wpabuf_len(hapd->wps_probe_resp_ie));
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pos += wpabuf_len(hapd->wps_probe_resp_ie);
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_WPS */
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_P2P
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if ((hapd->conf->p2p & P2P_ENABLED) && is_p2p &&
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    hapd->p2p_probe_resp_ie) {
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie),
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  wpabuf_len(hapd->p2p_probe_resp_ie));
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pos += wpabuf_len(hapd->p2p_probe_resp_ie);
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_P2P */
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_P2P_MANAGER
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    P2P_MANAGE)
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pos = hostapd_eid_p2p_manage(hapd, pos);
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_P2P_MANAGER */
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_HS20
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_hs20_indication(hapd, pos);
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_osen(hapd, pos);
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_HS20 */
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->conf->vendor_elements) {
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements),
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  wpabuf_len(hapd->conf->vendor_elements));
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pos += wpabuf_len(hapd->conf->vendor_elements);
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*resp_len = pos - (u8 *) resp;
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return (u8 *) resp;
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum ssid_match_result {
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	NO_SSID_MATCH,
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	EXACT_SSID_MATCH,
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	WILDCARD_SSID_MATCH
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic enum ssid_match_result ssid_match(struct hostapd_data *hapd,
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					 const u8 *ssid, size_t ssid_len,
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					 const u8 *ssid_list,
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					 size_t ssid_list_len)
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const u8 *pos, *end;
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int wildcard = 0;
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (ssid_len == 0)
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		wildcard = 1;
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (ssid_len == hapd->conf->ssid.ssid_len &&
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    os_memcmp(ssid, hapd->conf->ssid.ssid, ssid_len) == 0)
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return EXACT_SSID_MATCH;
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (ssid_list == NULL)
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = ssid_list;
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	end = ssid_list + ssid_list_len;
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	while (pos + 1 <= end) {
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (pos + 2 + pos[1] > end)
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			break;
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (pos[1] == 0)
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			wildcard = 1;
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (pos[1] == hapd->conf->ssid.ssid_len &&
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		    os_memcmp(pos + 2, hapd->conf->ssid.ssid, pos[1]) == 0)
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return EXACT_SSID_MATCH;
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pos += 2 + pos[1];
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH;
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid handle_probe_req(struct hostapd_data *hapd,
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		      const struct ieee80211_mgmt *mgmt, size_t len,
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		      int ssi_signal)
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	u8 *resp;
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct ieee802_11_elems elems;
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const u8 *ie;
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	size_t ie_len;
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct sta_info *sta = NULL;
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	size_t i, resp_len;
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int noack;
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	enum ssid_match_result res;
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ie = mgmt->u.probe_req.variable;
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req))
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req));
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++)
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx,
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					    mgmt->sa, mgmt->da, mgmt->bssid,
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					    ie, ie_len, ssi_signal) > 0)
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return;
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!hapd->iconf->send_probe_response)
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) {
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		wpa_printf(MSG_DEBUG, "Could not parse ProbeReq from " MACSTR,
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   MAC2STR(mgmt->sa));
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if ((!elems.ssid || !elems.supp_rates)) {
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request "
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   "without SSID or supported rates element",
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   MAC2STR(mgmt->sa));
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_P2P
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->p2p && elems.wps_ie) {
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		struct wpabuf *wps;
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		wps = ieee802_11_vendor_ie_concat(ie, ie_len, WPS_DEV_OUI_WFA);
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (wps && !p2p_group_match_dev_type(hapd->p2p_group, wps)) {
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request "
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   "due to mismatch with Requested Device "
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   "Type");
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			wpabuf_free(wps);
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return;
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		wpabuf_free(wps);
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->p2p && elems.p2p) {
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		struct wpabuf *p2p;
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		p2p = ieee802_11_vendor_ie_concat(ie, ie_len, P2P_IE_VENDOR_TYPE);
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (p2p && !p2p_group_match_dev_id(hapd->p2p_group, p2p)) {
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			wpa_printf(MSG_MSGDUMP, "P2P: Ignore Probe Request "
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   "due to mismatch with Device ID");
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			wpabuf_free(p2p);
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return;
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		wpabuf_free(p2p);
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_P2P */
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0 &&
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    elems.ssid_list_len == 0) {
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for "
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   "broadcast SSID ignored", MAC2STR(mgmt->sa));
5743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
5753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	sta = ap_get_sta(hapd, mgmt->sa);
5783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_P2P
5803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if ((hapd->conf->p2p & P2P_GROUP_OWNER) &&
5813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    elems.ssid_len == P2P_WILDCARD_SSID_LEN &&
5823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    os_memcmp(elems.ssid, P2P_WILDCARD_SSID,
5833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		      P2P_WILDCARD_SSID_LEN) == 0) {
5843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Process P2P Wildcard SSID like Wildcard SSID */
5853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		elems.ssid_len = 0;
5863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_P2P */
5883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	res = ssid_match(hapd, elems.ssid, elems.ssid_len,
5903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			 elems.ssid_list, elems.ssid_list_len);
5913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (res != NO_SSID_MATCH) {
5923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (sta)
5933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			sta->ssid_probe = &hapd->conf->ssid;
5943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} else {
5953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!(mgmt->da[0] & 0x01)) {
5963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
5973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   " for foreign SSID '%s' (DA " MACSTR ")%s",
5983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   MAC2STR(mgmt->sa),
5993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   wpa_ssid_txt(elems.ssid, elems.ssid_len),
6003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   MAC2STR(mgmt->da),
6013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   elems.ssid_list ? " (SSID list)" : "");
6023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
6043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_INTERWORKING
6073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->conf->interworking &&
6083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    elems.interworking && elems.interworking_len >= 1) {
6093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		u8 ant = elems.interworking[0] & 0x0f;
6103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (ant != INTERWORKING_ANT_WILDCARD &&
6113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		    ant != hapd->conf->access_network_type) {
6123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
6133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   " for mismatching ANT %u ignored",
6143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   MAC2STR(mgmt->sa), ant);
6153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return;
6163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->conf->interworking && elems.interworking &&
6203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    (elems.interworking_len == 7 || elems.interworking_len == 9)) {
6213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const u8 *hessid;
6223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (elems.interworking_len == 7)
6233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			hessid = elems.interworking + 1;
6243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
6253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			hessid = elems.interworking + 1 + 2;
6263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (!is_broadcast_ether_addr(hessid) &&
6273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		    os_memcmp(hessid, hapd->conf->hessid, ETH_ALEN) != 0) {
6283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR
6293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   " for mismatching HESSID " MACSTR
6303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   " ignored",
6313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				   MAC2STR(mgmt->sa), MAC2STR(hessid));
6323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return;
6333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
6343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_INTERWORKING */
6363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_P2P
6383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if ((hapd->conf->p2p & P2P_GROUP_OWNER) &&
6393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    supp_rates_11b_only(&elems)) {
6403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* Indicates support for 11b rates only */
6413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		wpa_printf(MSG_EXCESSIVE, "P2P: Ignore Probe Request from "
6423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   MACSTR " with only 802.11b rates",
6433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   MAC2STR(mgmt->sa));
6443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
6453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_P2P */
6473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* TODO: verify that supp_rates contains at least one matching rate
6493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * with AP configuration */
6503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_TESTING_OPTIONS
6523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->iconf->ignore_probe_probability > 0.0 &&
6533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    drand48() < hapd->iconf->ignore_probe_probability) {
6543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		wpa_printf(MSG_INFO,
6553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   "TESTING: ignoring probe request from " MACSTR,
6563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   MAC2STR(mgmt->sa));
6573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
6583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
6593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_TESTING_OPTIONS */
6603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	resp = hostapd_gen_probe_resp(hapd, sta, mgmt, elems.p2p != NULL,
6623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				      &resp_len);
6633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (resp == NULL)
6643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
6653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/*
6673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * If this is a broadcast probe request, apply no ack policy to avoid
6683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * excessive retries.
6693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 */
6703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	noack = !!(res == WILDCARD_SSID_MATCH &&
6713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   is_broadcast_ether_addr(mgmt->da));
6723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hostapd_drv_send_mlme(hapd, resp, resp_len, noack) < 0)
6743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		wpa_printf(MSG_INFO, "handle_probe_req: send failed");
6753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	os_free(resp);
6773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s "
6793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   "SSID", MAC2STR(mgmt->sa),
6803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		   elems.ssid_len == 0 ? "broadcast" : "our");
6813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
6823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6843c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd,
6853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					size_t *resp_len)
6863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
6873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* check probe response offloading caps and print warnings */
6883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD))
6893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return NULL;
6903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
6913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_WPS
6923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->conf->wps_state && hapd->wps_probe_resp_ie &&
6933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    (!(hapd->iface->probe_resp_offloads &
6943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	       (WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS |
6953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2))))
6963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		wpa_printf(MSG_WARNING, "Device is trying to offload WPS "
6973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   "Probe Response while not supporting this");
6983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_WPS */
6993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_P2P
7013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_probe_resp_ie &&
7023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    !(hapd->iface->probe_resp_offloads &
7033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	      WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P))
7043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		wpa_printf(MSG_WARNING, "Device is trying to offload P2P "
7053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   "Probe Response while not supporting this");
7063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif  /* CONFIG_P2P */
7073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->conf->interworking &&
7093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    !(hapd->iface->probe_resp_offloads &
7103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	      WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING))
7113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		wpa_printf(MSG_WARNING, "Device is trying to offload "
7123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   "Interworking Probe Response while not supporting "
7133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			   "this");
7143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Generate a Probe Response template for the non-P2P case */
7163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return hostapd_gen_probe_resp(hapd, NULL, NULL, 0, resp_len);
7173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
7183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* NEED_AP_MLME */
7203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7223c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint ieee802_11_build_ap_params(struct hostapd_data *hapd,
7233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			       struct wpa_driver_ap_params *params)
7243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
7253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct ieee80211_mgmt *head = NULL;
7263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	u8 *tail = NULL;
7273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	size_t head_len = 0, tail_len = 0;
7283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	u8 *resp = NULL;
7293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	size_t resp_len = 0;
7303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef NEED_AP_MLME
7313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	u16 capab_info;
7323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	u8 *pos, *tailpos;
7333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define BEACON_HEAD_BUF_SIZE 256
7353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#define BEACON_TAIL_BUF_SIZE 512
7363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	head = os_zalloc(BEACON_HEAD_BUF_SIZE);
7373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tail_len = BEACON_TAIL_BUF_SIZE;
7383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_WPS
7393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->conf->wps_state && hapd->wps_beacon_ie)
7403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tail_len += wpabuf_len(hapd->wps_beacon_ie);
7413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_WPS */
7423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_P2P
7433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->p2p_beacon_ie)
7443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tail_len += wpabuf_len(hapd->p2p_beacon_ie);
7453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_P2P */
7463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->conf->vendor_elements)
7473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tail_len += wpabuf_len(hapd->conf->vendor_elements);
7483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tailpos = tail = os_malloc(tail_len);
7493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (head == NULL || tail == NULL) {
7503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		wpa_printf(MSG_ERROR, "Failed to set beacon data");
7513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os_free(head);
7523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os_free(tail);
7533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return -1;
7543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT,
7573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					   WLAN_FC_STYPE_BEACON);
7583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	head->duration = host_to_le16(0);
7593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	os_memset(head->da, 0xff, ETH_ALEN);
7603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	os_memcpy(head->sa, hapd->own_addr, ETH_ALEN);
7623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN);
7633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	head->u.beacon.beacon_int =
7643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		host_to_le16(hapd->iconf->beacon_int);
7653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* hardware or low-level driver will setup seq_ctrl and timestamp */
7673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	capab_info = hostapd_own_capab_info(hapd, NULL, 0);
7683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	head->u.beacon.capab_info = host_to_le16(capab_info);
7693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = &head->u.beacon.variable[0];
7703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* SSID */
7723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	*pos++ = WLAN_EID_SSID;
7733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->conf->ignore_broadcast_ssid == 2) {
7743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		/* clear the data, but keep the correct length of the SSID */
7753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*pos++ = hapd->conf->ssid.ssid_len;
7763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os_memset(pos, 0, hapd->conf->ssid.ssid_len);
7773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pos += hapd->conf->ssid.ssid_len;
7783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} else if (hapd->conf->ignore_broadcast_ssid) {
7793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*pos++ = 0; /* empty SSID */
7803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} else {
7813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		*pos++ = hapd->conf->ssid.ssid_len;
7823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os_memcpy(pos, hapd->conf->ssid.ssid,
7833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  hapd->conf->ssid.ssid_len);
7843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		pos += hapd->conf->ssid.ssid_len;
7853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
7863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Supported rates */
7883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_supp_rates(hapd, pos);
7893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* DS Params */
7913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	pos = hostapd_eid_ds_params(hapd, pos);
7923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	head_len = pos - (u8 *) head;
7943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tailpos = hostapd_eid_country(hapd, tailpos,
7963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				      tail + BEACON_TAIL_BUF_SIZE - tailpos);
7973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
7983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Power Constraint element */
7993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tailpos = hostapd_eid_pwr_constraint(hapd, tailpos);
8003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* ERP Information element */
8023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tailpos = hostapd_eid_erp_info(hapd, tailpos);
8033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Extended supported rates */
8053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos);
8063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* RSN, MDIE, WPA */
8083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE -
8093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				  tailpos);
8103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tailpos = hostapd_eid_bss_load(hapd, tailpos,
8123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				       tail + BEACON_TAIL_BUF_SIZE - tailpos);
8133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_IEEE80211N
8153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tailpos = hostapd_eid_ht_capabilities(hapd, tailpos);
8163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tailpos = hostapd_eid_ht_operation(hapd, tailpos);
8173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_IEEE80211N */
8183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tailpos = hostapd_eid_ext_capab(hapd, tailpos);
8203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/*
8223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * TODO: Time Advertisement element should only be included in some
8233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 * DTIM Beacon frames.
8243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	 */
8253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tailpos = hostapd_eid_time_adv(hapd, tailpos);
8263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tailpos = hostapd_eid_interworking(hapd, tailpos);
8283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tailpos = hostapd_eid_adv_proto(hapd, tailpos);
8293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tailpos = hostapd_eid_roaming_consortium(hapd, tailpos);
8303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tailpos = hostapd_add_csa_elems(hapd, tailpos, tail,
8313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					&hapd->cs_c_off_beacon);
8323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_IEEE80211AC
8333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tailpos = hostapd_eid_vht_capabilities(hapd, tailpos);
8343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tailpos = hostapd_eid_vht_operation(hapd, tailpos);
8353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_IEEE80211AC */
8363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	/* Wi-Fi Alliance WMM */
8383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tailpos = hostapd_eid_wmm(hapd, tailpos);
8393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_WPS
8413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->conf->wps_state && hapd->wps_beacon_ie) {
8423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os_memcpy(tailpos, wpabuf_head(hapd->wps_beacon_ie),
8433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  wpabuf_len(hapd->wps_beacon_ie));
8443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tailpos += wpabuf_len(hapd->wps_beacon_ie);
8453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_WPS */
8473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_P2P
8493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_beacon_ie) {
8503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os_memcpy(tailpos, wpabuf_head(hapd->p2p_beacon_ie),
8513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  wpabuf_len(hapd->p2p_beacon_ie));
8523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tailpos += wpabuf_len(hapd->p2p_beacon_ie);
8533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_P2P */
8553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_P2P_MANAGER
8563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) ==
8573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    P2P_MANAGE)
8583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tailpos = hostapd_eid_p2p_manage(hapd, tailpos);
8593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_P2P_MANAGER */
8603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_HS20
8623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tailpos = hostapd_eid_hs20_indication(hapd, tailpos);
8633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tailpos = hostapd_eid_osen(hapd, tailpos);
8643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_HS20 */
8653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->conf->vendor_elements) {
8673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements),
8683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			  wpabuf_len(hapd->conf->vendor_elements));
8693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		tailpos += wpabuf_len(hapd->conf->vendor_elements);
8703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
8713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	tail_len = tailpos > tail ? tailpos - tail : 0;
8733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	resp = hostapd_probe_resp_offloads(hapd, &resp_len);
8753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* NEED_AP_MLME */
8763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
8773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	os_memset(params, 0, sizeof(*params));
8783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->head = (u8 *) head;
8793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->head_len = head_len;
8803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->tail = tail;
8813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->tail_len = tail_len;
8823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->proberesp = resp;
8833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->proberesp_len = resp_len;
8843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->dtim_period = hapd->conf->dtim_period;
8853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->beacon_int = hapd->iconf->beacon_int;
8863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->basic_rates = hapd->iface->basic_rates;
8873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->ssid = hapd->conf->ssid.ssid;
8883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->ssid_len = hapd->conf->ssid.ssid_len;
8893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->pairwise_ciphers = hapd->conf->wpa_pairwise |
8903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		hapd->conf->rsn_pairwise;
8913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->group_cipher = hapd->conf->wpa_group;
8923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->key_mgmt_suites = hapd->conf->wpa_key_mgmt;
8933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->auth_algs = hapd->conf->auth_algs;
8943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->wpa_version = hapd->conf->wpa;
8953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->privacy = hapd->conf->ssid.wep.keys_set || hapd->conf->wpa ||
8963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		(hapd->conf->ieee802_1x &&
8973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		 (hapd->conf->default_wep_key_len ||
8983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		  hapd->conf->individual_wep_key_len));
8993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	switch (hapd->conf->ignore_broadcast_ssid) {
9003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	case 0:
9013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params->hide_ssid = NO_SSID_HIDING;
9023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		break;
9033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	case 1:
9043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params->hide_ssid = HIDDEN_SSID_ZERO_LEN;
9053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		break;
9063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	case 2:
9073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params->hide_ssid = HIDDEN_SSID_ZERO_CONTENTS;
9083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		break;
9093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->isolate = hapd->conf->isolate;
9113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef NEED_AP_MLME
9123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->cts_protect = !!(ieee802_11_erp_info(hapd) &
9133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				ERP_INFO_USE_PROTECTION);
9143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->preamble = hapd->iface->num_sta_no_short_preamble == 0 &&
9153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		hapd->iconf->preamble == SHORT_PREAMBLE;
9163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->iface->current_mode &&
9173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G)
9183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params->short_slot_time =
9193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			hapd->iface->num_sta_no_short_slot_time > 0 ? 0 : 1;
9203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
9213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params->short_slot_time = -1;
9223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n)
9233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params->ht_opmode = -1;
9243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
9253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params->ht_opmode = hapd->iface->ht_op_mode;
9263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* NEED_AP_MLME */
9273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->interworking = hapd->conf->interworking;
9283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->conf->interworking &&
9293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    !is_zero_ether_addr(hapd->conf->hessid))
9303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params->hessid = hapd->conf->hessid;
9313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->access_network_type = hapd->conf->access_network_type;
9323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->ap_max_inactivity = hapd->conf->ap_max_inactivity;
9333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#ifdef CONFIG_HS20
9343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->disable_dgaf = hapd->conf->disable_dgaf;
9353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->conf->osen) {
9363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params->privacy = 1;
9373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params->osen = 1;
9383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_HS20 */
9403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return 0;
9413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9443c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid ieee802_11_free_ap_params(struct wpa_driver_ap_params *params)
9453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	os_free(params->tail);
9473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->tail = NULL;
9483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	os_free(params->head);
9493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->head = NULL;
9503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	os_free(params->proberesp);
9513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params->proberesp = NULL;
9523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
9533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9553c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint ieee802_11_set_beacon(struct hostapd_data *hapd)
9563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
9573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct wpa_driver_ap_params params;
9583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct hostapd_freq_params freq;
9593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct hostapd_iface *iface = hapd->iface;
9603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct hostapd_config *iconf = iface->conf;
9613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	struct wpabuf *beacon, *proberesp, *assocresp;
9623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int res, ret = -1;
9633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hapd->csa_in_progress) {
9653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		wpa_printf(MSG_ERROR, "Cannot set beacons during CSA period");
9663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return -1;
9673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
9683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	hapd->beacon_set_done = 1;
9703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (ieee802_11_build_ap_params(hapd, &params) < 0)
9723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return -1;
9733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) <
9753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    0)
9763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		goto fail;
9773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.beacon_ies = beacon;
9793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.proberesp_ies = proberesp;
9803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	params.assocresp_ies = assocresp;
9813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (iface->current_mode &&
9833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	    hostapd_set_freq_params(&freq, iconf->hw_mode, iface->freq,
9843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				    iconf->channel, iconf->ieee80211n,
9853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				    iconf->ieee80211ac,
9863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				    iconf->secondary_channel,
9873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				    iconf->vht_oper_chwidth,
9883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				    iconf->vht_oper_centr_freq_seg0_idx,
9893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				    iconf->vht_oper_centr_freq_seg1_idx,
9903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				    iface->current_mode->vht_capab) == 0)
9913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		params.freq = &freq;
9923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
9933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	res = hostapd_drv_set_ap(hapd, &params);
9943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp);
9953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (res)
9963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		wpa_printf(MSG_ERROR, "Failed to set beacon parameters");
9973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
9983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		ret = 0;
9993c827367444ee418f129b2c238299f49d3264554Jarkko Poyryfail:
10003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	ieee802_11_free_ap_params(&params);
10013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return ret;
10023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10053c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint ieee802_11_set_beacons(struct hostapd_iface *iface)
10063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	size_t i;
10083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int ret = 0;
10093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (i = 0; i < iface->num_bss; i++) {
10113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (iface->bss[i]->started &&
10123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		    ieee802_11_set_beacon(iface->bss[i]) < 0)
10133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ret = -1;
10143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return ret;
10173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/* only update beacons if started */
10213c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint ieee802_11_update_beacons(struct hostapd_iface *iface)
10223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
10233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	size_t i;
10243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int ret = 0;
10253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (i = 0; i < iface->num_bss; i++) {
10273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (iface->bss[i]->beacon_set_done && iface->bss[i]->started &&
10283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		    ieee802_11_set_beacon(iface->bss[i]) < 0)
10293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			ret = -1;
10303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
10313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return ret;
10333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
10343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
10353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#endif /* CONFIG_NATIVE_WINDOWS */
10363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry