static struct wpabuf * p2p_build_sd_response(u8 dialog_token, u16 status_code,
					     u16 comeback_delay,
					     u16 update_indic,
					     const struct wpabuf *tlvs)
{
	struct wpabuf *buf;
	u8 *len_pos;

	buf = gas_anqp_build_initial_resp(dialog_token, status_code,
					  comeback_delay,
					  100 + (tlvs ? wpabuf_len(tlvs) : 0));
	if (buf == NULL)
		return NULL;

	if (tlvs) {
		/* ANQP Query Response Frame */
		len_pos = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
		wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE);
		 /* Service Update Indicator */
		wpabuf_put_le16(buf, update_indic);
		wpabuf_put_buf(buf, tlvs);
		gas_anqp_set_element_len(buf, len_pos);
	}

	gas_anqp_set_len(buf);

	return buf;
}
Example #2
0
struct wpabuf * mbo_build_anqp_buf(struct wpa_supplicant *wpa_s,
				   struct wpa_bss *bss)
{
	struct wpabuf *anqp_buf;
	u8 *len_pos;

	if (!wpa_bss_get_vendor_ie(bss, MBO_IE_VENDOR_TYPE)) {
		wpa_printf(MSG_INFO, "MBO: " MACSTR
			   " does not support MBO - cannot request MBO ANQP elements from it",
			   MAC2STR(bss->bssid));
		return NULL;
	}

	anqp_buf = wpabuf_alloc(10);
	if (!anqp_buf)
		return NULL;

	len_pos = gas_anqp_add_element(anqp_buf, ANQP_VENDOR_SPECIFIC);
	wpabuf_put_be24(anqp_buf, OUI_WFA);
	wpabuf_put_u8(anqp_buf, MBO_ANQP_OUI_TYPE);

	wpabuf_put_u8(anqp_buf, MBO_ANQP_SUBTYPE_CELL_CONN_PREF);
	gas_anqp_set_element_len(anqp_buf, len_pos);

	return anqp_buf;
}
static void anqp_add_venue_name(struct hostapd_data *hapd, struct wpabuf *buf,
				struct gas_dialog_info *di)
{
	if (hapd->conf->hs20_venue_name) {
		wpabuf_put_le16(buf, ANQP_VENUE_NAME);
		wpabuf_put_le16(buf, hapd->conf->hs20_venue_name_len);
		wpabuf_put_data(buf, hapd->conf->hs20_venue_name,
				hapd->conf->hs20_venue_name_len);
	} else if (hapd->conf->venue_name) {
		u8 *len;
		unsigned int i;
		len = gas_anqp_add_element(buf, ANQP_VENUE_NAME);
		wpabuf_put_u8(buf, hapd->conf->venue_group);
		wpabuf_put_u8(buf, hapd->conf->venue_type);
		for (i = 0; i < hapd->conf->venue_name_count; i++) {
			struct hostapd_venue_name *vn;
			vn = &hapd->conf->venue_name[i];
			wpabuf_put_u8(buf, 3 + vn->name_len);
			wpabuf_put_data(buf, vn->lang, 3);
			wpabuf_put_data(buf, vn->name, vn->name_len);
		}
		gas_anqp_set_element_len(buf, len);
	} else if (di) {
		wpabuf_put_data(buf, di->venue_name, di->venue_name_len);
	}
}
static void anqp_add_hs_capab_list(struct hostapd_data *hapd,
				   struct wpabuf *buf)
{
	u8 *len;

	len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
	wpabuf_put_be24(buf, OUI_WFA);
	wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
	wpabuf_put_u8(buf, HS20_STYPE_CAPABILITY_LIST);
	wpabuf_put_u8(buf, 0); /* Reserved */
	wpabuf_put_u8(buf, HS20_STYPE_CAPABILITY_LIST);
	if (hapd->conf->hs20_operator_friendly_name ||
	    (hapd->anqp_type_mask & ANQP_REQ_OPERATOR_FRIENDLY_NAME))
		wpabuf_put_u8(buf, HS20_STYPE_OPERATOR_FRIENDLY_NAME);
	if (hapd->conf->hs20_wan_metrics ||
	    (hapd->anqp_type_mask & ANQP_REQ_WAN_METRICS))
		wpabuf_put_u8(buf, HS20_STYPE_WAN_METRICS);
	if (hapd->conf->hs20_connection_capability ||
	    (hapd->anqp_type_mask & ANQP_REQ_CONNECTION_CAPABILITY))
		wpabuf_put_u8(buf, HS20_STYPE_CONNECTION_CAPABILITY);
	if (hapd->anqp_type_mask & ANQP_REQ_NAI_HOME_REALM)
		wpabuf_put_u8(buf, HS20_STYPE_NAI_HOME_REALM_QUERY);
	if (hapd->conf->hs20_operating_class ||
	    (hapd->anqp_type_mask & ANQP_REQ_OPERATING_CLASS))
		wpabuf_put_u8(buf, HS20_STYPE_OPERATING_CLASS);
	gas_anqp_set_element_len(buf, len);
}
static void anqp_add_capab_list(struct hostapd_data *hapd,
				struct wpabuf *buf)
{
	u8 *len;

	len = gas_anqp_add_element(buf, ANQP_CAPABILITY_LIST);
	wpabuf_put_le16(buf, ANQP_CAPABILITY_LIST);
	if (hapd->conf->venue_name || hapd->conf->hs20_venue_name ||
	    (hapd->anqp_type_mask & ANQP_REQ_VENUE_NAME))
		wpabuf_put_le16(buf, ANQP_VENUE_NAME);
	if (hapd->conf->hs20_network_auth_type ||
	    (hapd->anqp_type_mask & ANQP_REQ_NETWORK_AUTH_TYPE))
		wpabuf_put_le16(buf, ANQP_NETWORK_AUTH_TYPE);
	if (hapd->conf->roaming_consortium ||
	    (hapd->anqp_type_mask & ANQP_REQ_ROAMING_CONSORTIUM))
		wpabuf_put_le16(buf, ANQP_ROAMING_CONSORTIUM);
	if (hapd->conf->hs20_ipaddr_type_configured ||
	    (hapd->anqp_type_mask & ANQP_REQ_IP_ADDR_TYPE_AVAILABILITY))
		wpabuf_put_le16(buf, ANQP_IP_ADDR_TYPE_AVAILABILITY);
	if (hapd->conf->hs20_nai_realm_list ||
	    hapd->conf->nai_realm_data ||
	    (hapd->anqp_type_mask & ANQP_REQ_NAI_REALM))
		wpabuf_put_le16(buf, ANQP_NAI_REALM);
	if (hapd->conf->hs20_3gpp_cellular_network ||
	    (hapd->anqp_type_mask & ANQP_REQ_3GPP_CELLULAR_NETWORK))
		wpabuf_put_le16(buf, ANQP_3GPP_CELLULAR_NETWORK);
	if (hapd->conf->hs20_domain_name_list_value ||
	    (hapd->anqp_type_mask & ANQP_REQ_DOMAIN_NAME))
		wpabuf_put_le16(buf, ANQP_DOMAIN_NAME);
	anqp_add_hs_capab_list(hapd, buf);
	gas_anqp_set_element_len(buf, len);
}
Example #6
0
static void anqp_add_nai_realm(struct hostapd_data *hapd, struct wpabuf *buf,
			       const u8 *home_realm, size_t home_realm_len,
			       int nai_realm, int nai_home_realm)
{
	if (nai_realm && hapd->conf->nai_realm_data) {
		u8 *len;
		unsigned int i, j;
		len = gas_anqp_add_element(buf, ANQP_NAI_REALM);
		wpabuf_put_le16(buf, hapd->conf->nai_realm_count);
		for (i = 0; i < hapd->conf->nai_realm_count; i++) {
			u8 *realm_data_len, *realm_len;
			struct hostapd_nai_realm_data *realm;

			realm = &hapd->conf->nai_realm_data[i];
			realm_data_len = wpabuf_put(buf, 2);
			wpabuf_put_u8(buf, realm->encoding);
			realm_len = wpabuf_put(buf, 1);
			for (j = 0; realm->realm[j]; j++) {
				if (j > 0)
					wpabuf_put_u8(buf, ';');
				wpabuf_put_str(buf, realm->realm[j]);
			}
			*realm_len = (u8 *) wpabuf_put(buf, 0) - realm_len - 1;
			anqp_add_nai_realm_eap(buf, realm);
			gas_anqp_set_element_len(buf, realm_data_len);
		}
		gas_anqp_set_element_len(buf, len);
	} else if (nai_home_realm && hapd->conf->nai_realm_data) {
		hs20_add_nai_home_realm_matches(hapd, buf, home_realm,
						home_realm_len);
	}
}
void hs20_put_anqp_req(u32 stypes, const u8 *payload, size_t payload_len,
		       struct wpabuf *buf)
{
	u8 *len_pos;

	if (buf == NULL)
		return;

	len_pos = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
	wpabuf_put_be24(buf, OUI_WFA);
	wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
	if (stypes == BIT(HS20_STYPE_NAI_HOME_REALM_QUERY)) {
		wpabuf_put_u8(buf, HS20_STYPE_NAI_HOME_REALM_QUERY);
		wpabuf_put_u8(buf, 0); /* Reserved */
		if (payload)
			wpabuf_put_data(buf, payload, payload_len);
	} else if (stypes == BIT(HS20_STYPE_ICON_REQUEST)) {
		wpabuf_put_u8(buf, HS20_STYPE_ICON_REQUEST);
		wpabuf_put_u8(buf, 0); /* Reserved */
		if (payload)
			wpabuf_put_data(buf, payload, payload_len);
	} else {
		u8 i;
		wpabuf_put_u8(buf, HS20_STYPE_QUERY_LIST);
		wpabuf_put_u8(buf, 0); /* Reserved */
		for (i = 0; i < 32; i++) {
			if (stypes & BIT(i))
				wpabuf_put_u8(buf, i);
		}
	}
	gas_anqp_set_element_len(buf, len_pos);

	gas_anqp_set_len(buf);
}
Example #8
0
static void anqp_add_osu_providers_list(struct hostapd_data *hapd,
					struct wpabuf *buf)
{
	if (hapd->conf->hs20_osu_providers_count) {
		size_t i;
		u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
		wpabuf_put_be24(buf, OUI_WFA);
		wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
		wpabuf_put_u8(buf, HS20_STYPE_OSU_PROVIDERS_LIST);
		wpabuf_put_u8(buf, 0); /* Reserved */

		/* OSU SSID */
		wpabuf_put_u8(buf, hapd->conf->osu_ssid_len);
		wpabuf_put_data(buf, hapd->conf->osu_ssid,
				hapd->conf->osu_ssid_len);

		/* Number of OSU Providers */
		wpabuf_put_u8(buf, hapd->conf->hs20_osu_providers_count);

		for (i = 0; i < hapd->conf->hs20_osu_providers_count; i++) {
			anqp_add_osu_provider(
				buf, hapd->conf,
				&hapd->conf->hs20_osu_providers[i]);
		}

		gas_anqp_set_element_len(buf, len);
	}
}
Example #9
0
static void anqp_add_hs_capab_list(struct hostapd_data *hapd,
				   struct wpabuf *buf)
{
	u8 *len;

	len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
	wpabuf_put_be24(buf, OUI_WFA);
	wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
	wpabuf_put_u8(buf, HS20_STYPE_CAPABILITY_LIST);
	wpabuf_put_u8(buf, 0); /* Reserved */
	wpabuf_put_u8(buf, HS20_STYPE_CAPABILITY_LIST);
	if (hapd->conf->hs20_oper_friendly_name)
		wpabuf_put_u8(buf, HS20_STYPE_OPERATOR_FRIENDLY_NAME);
	if (hapd->conf->hs20_wan_metrics)
		wpabuf_put_u8(buf, HS20_STYPE_WAN_METRICS);
	if (hapd->conf->hs20_connection_capability)
		wpabuf_put_u8(buf, HS20_STYPE_CONNECTION_CAPABILITY);
	if (hapd->conf->nai_realm_data)
		wpabuf_put_u8(buf, HS20_STYPE_NAI_HOME_REALM_QUERY);
	if (hapd->conf->hs20_operating_class)
		wpabuf_put_u8(buf, HS20_STYPE_OPERATING_CLASS);
	if (hapd->conf->hs20_osu_providers_count)
		wpabuf_put_u8(buf, HS20_STYPE_OSU_PROVIDERS_LIST);
	if (hapd->conf->hs20_icons_count)
		wpabuf_put_u8(buf, HS20_STYPE_ICON_REQUEST);
	gas_anqp_set_element_len(buf, len);
}
Example #10
0
static void anqp_add_capab_list(struct hostapd_data *hapd,
				struct wpabuf *buf)
{
	u8 *len;

	len = gas_anqp_add_element(buf, ANQP_CAPABILITY_LIST);
	wpabuf_put_le16(buf, ANQP_CAPABILITY_LIST);
	if (hapd->conf->venue_name)
		wpabuf_put_le16(buf, ANQP_VENUE_NAME);
	if (hapd->conf->network_auth_type)
		wpabuf_put_le16(buf, ANQP_NETWORK_AUTH_TYPE);
	if (hapd->conf->roaming_consortium)
		wpabuf_put_le16(buf, ANQP_ROAMING_CONSORTIUM);
	if (hapd->conf->ipaddr_type_configured)
		wpabuf_put_le16(buf, ANQP_IP_ADDR_TYPE_AVAILABILITY);
	if (hapd->conf->nai_realm_data)
		wpabuf_put_le16(buf, ANQP_NAI_REALM);
	if (hapd->conf->anqp_3gpp_cell_net)
		wpabuf_put_le16(buf, ANQP_3GPP_CELLULAR_NETWORK);
	if (hapd->conf->domain_name)
		wpabuf_put_le16(buf, ANQP_DOMAIN_NAME);
#ifdef CONFIG_HS20
	anqp_add_hs_capab_list(hapd, buf);
#endif /* CONFIG_HS20 */
	gas_anqp_set_element_len(buf, len);
}
Example #11
0
static void anqp_add_capab_list(struct hostapd_data *hapd,
				struct wpabuf *buf)
{
	u8 *len;
	u16 id;

	if (anqp_add_override(hapd, buf, ANQP_CAPABILITY_LIST))
		return;

	len = gas_anqp_add_element(buf, ANQP_CAPABILITY_LIST);
	wpabuf_put_le16(buf, ANQP_CAPABILITY_LIST);
	if (hapd->conf->venue_name || get_anqp_elem(hapd, ANQP_VENUE_NAME))
		wpabuf_put_le16(buf, ANQP_VENUE_NAME);
	if (get_anqp_elem(hapd, ANQP_EMERGENCY_CALL_NUMBER))
		wpabuf_put_le16(buf, ANQP_EMERGENCY_CALL_NUMBER);
	if (hapd->conf->network_auth_type ||
	    get_anqp_elem(hapd, ANQP_NETWORK_AUTH_TYPE))
		wpabuf_put_le16(buf, ANQP_NETWORK_AUTH_TYPE);
	if (hapd->conf->roaming_consortium ||
	    get_anqp_elem(hapd, ANQP_ROAMING_CONSORTIUM))
		wpabuf_put_le16(buf, ANQP_ROAMING_CONSORTIUM);
	if (hapd->conf->ipaddr_type_configured ||
	    get_anqp_elem(hapd, ANQP_IP_ADDR_TYPE_AVAILABILITY))
		wpabuf_put_le16(buf, ANQP_IP_ADDR_TYPE_AVAILABILITY);
	if (hapd->conf->nai_realm_data ||
	    get_anqp_elem(hapd, ANQP_NAI_REALM))
		wpabuf_put_le16(buf, ANQP_NAI_REALM);
	if (hapd->conf->anqp_3gpp_cell_net ||
	    get_anqp_elem(hapd, ANQP_3GPP_CELLULAR_NETWORK))
		wpabuf_put_le16(buf, ANQP_3GPP_CELLULAR_NETWORK);
	if (get_anqp_elem(hapd, ANQP_AP_GEOSPATIAL_LOCATION))
		wpabuf_put_le16(buf, ANQP_AP_GEOSPATIAL_LOCATION);
	if (get_anqp_elem(hapd, ANQP_AP_CIVIC_LOCATION))
		wpabuf_put_le16(buf, ANQP_AP_CIVIC_LOCATION);
	if (get_anqp_elem(hapd, ANQP_AP_LOCATION_PUBLIC_URI))
		wpabuf_put_le16(buf, ANQP_AP_LOCATION_PUBLIC_URI);
	if (hapd->conf->domain_name || get_anqp_elem(hapd, ANQP_DOMAIN_NAME))
		wpabuf_put_le16(buf, ANQP_DOMAIN_NAME);
	if (get_anqp_elem(hapd, ANQP_EMERGENCY_ALERT_URI))
		wpabuf_put_le16(buf, ANQP_EMERGENCY_ALERT_URI);
	if (get_anqp_elem(hapd, ANQP_EMERGENCY_NAI))
		wpabuf_put_le16(buf, ANQP_EMERGENCY_NAI);
	if (get_anqp_elem(hapd, ANQP_NEIGHBOR_REPORT))
		wpabuf_put_le16(buf, ANQP_NEIGHBOR_REPORT);
	for (id = 273; id < 277; id++) {
		if (get_anqp_elem(hapd, id))
			wpabuf_put_le16(buf, id);
	}
	if (get_anqp_elem(hapd, ANQP_VENUE_URL))
		wpabuf_put_le16(buf, ANQP_VENUE_URL);
	if (get_anqp_elem(hapd, ANQP_ADVICE_OF_CHARGE))
		wpabuf_put_le16(buf, ANQP_ADVICE_OF_CHARGE);
	if (get_anqp_elem(hapd, ANQP_LOCAL_CONTENT))
		wpabuf_put_le16(buf, ANQP_LOCAL_CONTENT);
#ifdef CONFIG_HS20
	anqp_add_hs_capab_list(hapd, buf);
#endif /* CONFIG_HS20 */
	gas_anqp_set_element_len(buf, len);
}
static void anqp_add_nai_realm(struct hostapd_data *hapd, struct wpabuf *buf,
			       struct gas_dialog_info *di,
			       struct anqp_query_info *qi, int nai_realm,
			       int nai_home_realm)
{
	/* dynamically set nai_realm_list overrides static configuration */
	if (nai_realm && hapd->conf->hs20_nai_realm_list) {
		wpabuf_put_le16(buf, ANQP_NAI_REALM);
		wpabuf_put_le16(buf, hapd->conf->hs20_nai_realm_list_len);
		wpabuf_put_data(buf, hapd->conf->hs20_nai_realm_list,
				hapd->conf->hs20_nai_realm_list_len);
	} else if (nai_realm && hapd->conf->nai_realm_data) {
		u8 *len;
		unsigned int i, j;
		len = gas_anqp_add_element(buf, ANQP_NAI_REALM);
		wpabuf_put_le16(buf, hapd->conf->nai_realm_count);
		for (i = 0; i < hapd->conf->nai_realm_count; i++) {
			u8 *realm_data_len, *realm_len;
			struct hostapd_nai_realm_data *realm;

			realm = &hapd->conf->nai_realm_data[i];
			realm_data_len = wpabuf_put(buf, 2);
			wpabuf_put_u8(buf, realm->encoding);
			realm_len = wpabuf_put(buf, 1);
			for (j = 0; realm->realm[j]; j++) {
				if (j > 0)
					wpabuf_put_u8(buf, ';');
				wpabuf_put_str(buf, realm->realm[j]);
			}
			*realm_len = (u8 *) wpabuf_put(buf, 0) - realm_len - 1;
			if (realm->num_auths) {
				wpabuf_put_u8(buf, 1); /* EAP method count */
				wpabuf_put_u8(buf, 2 + (3 * realm->num_auths));
				wpabuf_put_u8(buf, realm->eap_method);
				wpabuf_put_u8(buf, realm->num_auths);
				for (j = 0; j < realm->num_auths; j++) {
					wpabuf_put_u8(buf, realm->auth_id[j]);
					wpabuf_put_u8(buf, 1);
					wpabuf_put_u8(buf, realm->auth_val[j]);
				}
			} else {
				wpabuf_put_u8(buf, 0); /* EAP method count */
			}
			gas_anqp_set_element_len(buf, realm_data_len);
		}
		gas_anqp_set_element_len(buf, len);
	} else if (nai_home_realm && hapd->conf->nai_realm_data) {
		process_hs_nai_home_realm(hapd, buf, qi);
	} else if (di) {
		if (nai_realm)
			wpabuf_put_data(buf, di->nai_realm,
					di->nai_realm_len);
		if (nai_home_realm)
			wpabuf_put_data(buf, di->nai_home_realm,
					di->nai_home_realm_len);
	}
}
Example #13
0
static void anqp_add_icon_binary_file(struct hostapd_data *hapd,
				      struct wpabuf *buf,
				      const u8 *name, size_t name_len)
{
	struct hs20_icon *icon;
	size_t i;
	u8 *len;

	wpa_hexdump_ascii(MSG_DEBUG, "HS 2.0: Requested Icon Filename",
			  name, name_len);
	for (i = 0; i < hapd->conf->hs20_icons_count; i++) {
		icon = &hapd->conf->hs20_icons[i];
		if (name_len == os_strlen(icon->name) &&
		    os_memcmp(name, icon->name, name_len) == 0)
			break;
	}

	if (i < hapd->conf->hs20_icons_count)
		icon = &hapd->conf->hs20_icons[i];
	else
		icon = NULL;

	len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
	wpabuf_put_be24(buf, OUI_WFA);
	wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
	wpabuf_put_u8(buf, HS20_STYPE_ICON_BINARY_FILE);
	wpabuf_put_u8(buf, 0); /* Reserved */

	if (icon) {
		char *data;
		size_t data_len;

		data = os_readfile(icon->file, &data_len);
		if (data == NULL || data_len > 65535) {
			wpabuf_put_u8(buf, 2); /* Download Status:
						* Unspecified file error */
			wpabuf_put_u8(buf, 0);
			wpabuf_put_le16(buf, 0);
		} else {
			wpabuf_put_u8(buf, 0); /* Download Status: Success */
			wpabuf_put_u8(buf, os_strlen(icon->type));
			wpabuf_put_str(buf, icon->type);
			wpabuf_put_le16(buf, data_len);
			wpabuf_put_data(buf, data, data_len);
		}
		os_free(data);
	} else {
		wpabuf_put_u8(buf, 1); /* Download Status: File not found */
		wpabuf_put_u8(buf, 0);
		wpabuf_put_le16(buf, 0);
	}

	gas_anqp_set_element_len(buf, len);
}
Example #14
0
static void anqp_add_wan_metrics(struct hostapd_data *hapd,
				 struct wpabuf *buf)
{
	if (hapd->conf->hs20_wan_metrics) {
		u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
		wpabuf_put_be24(buf, OUI_WFA);
		wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
		wpabuf_put_u8(buf, HS20_STYPE_WAN_METRICS);
		wpabuf_put_u8(buf, 0); /* Reserved */
		wpabuf_put_data(buf, hapd->conf->hs20_wan_metrics, 13);
		gas_anqp_set_element_len(buf, len);
	}
}
Example #15
0
static void anqp_add_operating_class(struct hostapd_data *hapd,
				     struct wpabuf *buf)
{
	if (hapd->conf->hs20_operating_class) {
		u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
		wpabuf_put_be24(buf, OUI_WFA);
		wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
		wpabuf_put_u8(buf, HS20_STYPE_OPERATING_CLASS);
		wpabuf_put_u8(buf, 0); /* Reserved */
		wpabuf_put_data(buf, hapd->conf->hs20_operating_class,
				hapd->conf->hs20_operating_class_len);
		gas_anqp_set_element_len(buf, len);
	}
}
Example #16
0
static void anqp_add_connection_capability(struct hostapd_data *hapd,
					   struct wpabuf *buf)
{
	if (hapd->conf->hs20_connection_capability) {
		u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
		wpabuf_put_be24(buf, OUI_WFA);
		wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
		wpabuf_put_u8(buf, HS20_STYPE_CONNECTION_CAPABILITY);
		wpabuf_put_u8(buf, 0); /* Reserved */
		wpabuf_put_data(buf, hapd->conf->hs20_connection_capability,
				hapd->conf->hs20_connection_capability_len);
		gas_anqp_set_element_len(buf, len);
	}
}
Example #17
0
static void anqp_add_roaming_consortium(struct hostapd_data *hapd,
					struct wpabuf *buf)
{
	unsigned int i;
	u8 *len;

	len = gas_anqp_add_element(buf, ANQP_ROAMING_CONSORTIUM);
	for (i = 0; i < hapd->conf->roaming_consortium_count; i++) {
		struct hostapd_roaming_consortium *rc;
		rc = &hapd->conf->roaming_consortium[i];
		wpabuf_put_u8(buf, rc->len);
		wpabuf_put_data(buf, rc->oi, rc->len);
	}
	gas_anqp_set_element_len(buf, len);
}
static void anqp_add_operator_friendly_name(struct hostapd_data *hapd,
					    struct wpabuf *buf,
					    struct gas_dialog_info *di)
{
	if (hapd->conf->hs20_operator_friendly_name) {
		u8 *len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
		wpabuf_put_be24(buf, OUI_WFA);
		wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
		wpabuf_put_u8(buf, HS20_STYPE_OPERATOR_FRIENDLY_NAME);
		wpabuf_put_u8(buf, 0); /* Reserved */
		wpabuf_put_data(buf, hapd->conf->hs20_operator_friendly_name,
				hapd->conf->hs20_operator_friendly_name_len);
		gas_anqp_set_element_len(buf, len);
	} else if (di) {
		wpabuf_put_data(buf, di->oper_friendly_name,
				di->oper_friendly_name_len);
	}
}
static struct wpabuf * p2p_build_sd_query(u16 update_indic,
					  struct wpabuf *tlvs)
{
	struct wpabuf *buf;
	u8 *len_pos;

	buf = gas_anqp_build_initial_req(0, 100 + wpabuf_len(tlvs));
	if (buf == NULL)
		return NULL;

	/* ANQP Query Request Frame */
	len_pos = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
	wpabuf_put_be32(buf, P2P_IE_VENDOR_TYPE);
	wpabuf_put_le16(buf, update_indic); /* Service Update Indicator */
	wpabuf_put_buf(buf, tlvs);
	gas_anqp_set_element_len(buf, len_pos);

	gas_anqp_set_len(buf);

	return buf;
}
Example #20
0
static void anqp_add_venue_name(struct hostapd_data *hapd, struct wpabuf *buf)
{
	if (anqp_add_override(hapd, buf, ANQP_VENUE_NAME))
		return;

	if (hapd->conf->venue_name) {
		u8 *len;
		unsigned int i;
		len = gas_anqp_add_element(buf, ANQP_VENUE_NAME);
		wpabuf_put_u8(buf, hapd->conf->venue_group);
		wpabuf_put_u8(buf, hapd->conf->venue_type);
		for (i = 0; i < hapd->conf->venue_name_count; i++) {
			struct hostapd_lang_string *vn;
			vn = &hapd->conf->venue_name[i];
			wpabuf_put_u8(buf, 3 + vn->name_len);
			wpabuf_put_data(buf, vn->lang, 3);
			wpabuf_put_data(buf, vn->name, vn->name_len);
		}
		gas_anqp_set_element_len(buf, len);
	}
}
Example #21
0
static void anqp_add_operator_friendly_name(struct hostapd_data *hapd,
					    struct wpabuf *buf)
{
	if (hapd->conf->hs20_oper_friendly_name) {
		u8 *len;
		unsigned int i;
		len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
		wpabuf_put_be24(buf, OUI_WFA);
		wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
		wpabuf_put_u8(buf, HS20_STYPE_OPERATOR_FRIENDLY_NAME);
		wpabuf_put_u8(buf, 0); /* Reserved */
		for (i = 0; i < hapd->conf->hs20_oper_friendly_name_count; i++)
		{
			struct hostapd_lang_string *vn;
			vn = &hapd->conf->hs20_oper_friendly_name[i];
			wpabuf_put_u8(buf, 3 + vn->name_len);
			wpabuf_put_data(buf, vn->lang, 3);
			wpabuf_put_data(buf, vn->name, vn->name_len);
		}
		gas_anqp_set_element_len(buf, len);
	}
}
Example #22
0
static struct wpabuf * anqp_build_req(u16 info_ids[], size_t num_ids,
				      struct wpabuf *extra)
{
	struct wpabuf *buf;
	size_t i;
	u8 *len_pos;

	buf = gas_anqp_build_initial_req(0, 4 + num_ids * 2 +
					 (extra ? wpabuf_len(extra) : 0));
	if (buf == NULL)
		return NULL;

	len_pos = gas_anqp_add_element(buf, ANQP_QUERY_LIST);
	for (i = 0; i < num_ids; i++)
		wpabuf_put_le16(buf, info_ids[i]);
	gas_anqp_set_element_len(buf, len_pos);
	if (extra)
		wpabuf_put_buf(buf, extra);

	gas_anqp_set_len(buf);

	return buf;
}
Example #23
0
static int hs20_add_nai_home_realm_matches(struct hostapd_data *hapd,
					   struct wpabuf *buf,
					   const u8 *home_realm,
					   size_t home_realm_len)
{
	unsigned int i, j, k;
	u8 num_realms, num_matching = 0, encoding, realm_len, *realm_list_len;
	struct hostapd_nai_realm_data *realm;
	const u8 *pos, *realm_name, *end;
	struct {
		unsigned int realm_data_idx;
		unsigned int realm_idx;
	} matches[10];

	pos = home_realm;
	end = pos + home_realm_len;
	if (pos + 1 > end) {
		wpa_hexdump(MSG_DEBUG, "Too short NAI Home Realm Query",
			    home_realm, home_realm_len);
		return -1;
	}
	num_realms = *pos++;

	for (i = 0; i < num_realms && num_matching < 10; i++) {
		if (pos + 2 > end) {
			wpa_hexdump(MSG_DEBUG,
				    "Truncated NAI Home Realm Query",
				    home_realm, home_realm_len);
			return -1;
		}
		encoding = *pos++;
		realm_len = *pos++;
		if (pos + realm_len > end) {
			wpa_hexdump(MSG_DEBUG,
				    "Truncated NAI Home Realm Query",
				    home_realm, home_realm_len);
			return -1;
		}
		realm_name = pos;
		for (j = 0; j < hapd->conf->nai_realm_count &&
			     num_matching < 10; j++) {
			const u8 *rpos, *rend;
			realm = &hapd->conf->nai_realm_data[j];
			if (encoding != realm->encoding)
				continue;

			rpos = realm_name;
			while (rpos < realm_name + realm_len &&
			       num_matching < 10) {
				for (rend = rpos;
				     rend < realm_name + realm_len; rend++) {
					if (*rend == ';')
						break;
				}
				for (k = 0; k < MAX_NAI_REALMS &&
					     realm->realm[k] &&
					     num_matching < 10; k++) {
					if ((int) os_strlen(realm->realm[k]) !=
					    rend - rpos ||
					    os_strncmp((char *) rpos,
						       realm->realm[k],
						       rend - rpos) != 0)
						continue;
					matches[num_matching].realm_data_idx =
						j;
					matches[num_matching].realm_idx = k;
					num_matching++;
				}
				rpos = rend + 1;
			}
		}
		pos += realm_len;
	}

	realm_list_len = gas_anqp_add_element(buf, ANQP_NAI_REALM);
	wpabuf_put_le16(buf, num_matching);

	/*
	 * There are two ways to format. 1. each realm in a NAI Realm Data unit
	 * 2. all realms that share the same EAP methods in a NAI Realm Data
	 * unit. The first format is likely to be bigger in size than the
	 * second, but may be easier to parse and process by the receiver.
	 */
	for (i = 0; i < num_matching; i++) {
		wpa_printf(MSG_DEBUG, "realm_idx %d, realm_data_idx %d",
			   matches[i].realm_data_idx, matches[i].realm_idx);
		realm = &hapd->conf->nai_realm_data[matches[i].realm_data_idx];
		anqp_add_nai_realm_data(buf, realm, matches[i].realm_idx);
	}
	gas_anqp_set_element_len(buf, realm_list_len);
	return 0;
}
static int process_hs_nai_home_realm(struct hostapd_data *hapd,
				     struct wpabuf *buf,
				     struct anqp_query_info *qi)
{
	unsigned int i, j, k;
	u8 num_realms, num_matching = 0, encoding, realm_len, *realm_list_len;
	struct hostapd_nai_realm_data *realm;
	const u8 *pos, *realm_name, *end;
	struct {
		unsigned int realm_data_idx;
		unsigned int realm_idx;
	} matches[10];

	pos = qi->param;
	end = pos + qi->param_arg;
	num_realms = *pos++;

	for (i = 0; i < num_realms && num_matching < 10; i++) {
		encoding = *pos++;
		realm_len = *pos++;
		realm_name = pos;
		for (j = 0; j < hapd->conf->nai_realm_count &&
			     num_matching < 10; j++) {
			realm = &hapd->conf->nai_realm_data[j];
			if (encoding != realm->encoding)
				continue;
			for (k = 0; realm->realm[k] && num_matching < 10; k++)
			{
				if (os_strncmp((char *) realm_name,
					       realm->realm[k], realm_len) !=
				    0)
					continue;
				matches[num_matching].realm_data_idx = j;
				matches[num_matching].realm_idx = k;
				num_matching++;
			}
		}
		pos += realm_len;
		if (pos > end) {
			wpa_hexdump(MSG_ERROR, "NAI Home Realm processing "
				    "error", qi->param, qi->param_arg);
			return -1;
		}
	}

	realm_list_len = gas_anqp_add_element(buf, ANQP_NAI_REALM);
	wpabuf_put_le16(buf, num_matching);

	/*
	 * There are two ways to format. 1. each realm in a NAI Realm Data unit
	 * 2. all realms that share the same EAP methods in a NAI Realm Data
	 * unit. The first format is likely to be bigger in size than the
	 * second, but may be easier to parse and process by the receiver.
	 */
	for (i = 0; i < num_matching; i++) {
		wpa_printf(MSG_DEBUG, "realm_idx %d, realm_data_idx %d",
			   matches[i].realm_data_idx, matches[i].realm_idx);
		realm = &hapd->conf->nai_realm_data[matches[i].realm_data_idx];
		anqp_add_nai_realm_data(buf, realm, matches[i].realm_idx);
	}
	gas_anqp_set_element_len(buf, realm_list_len);
	return 0;
}