11f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/* 21f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Generic advertisement service (GAS) (IEEE 802.11u) 31f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Copyright (c) 2009, Atheros Communications 461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidt * Copyright (c) 2011-2012, Qualcomm Atheros 51f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * 6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license. 7c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details. 81f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 91f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "includes.h" 111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "common.h" 131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "ieee802_11_defs.h" 141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt#include "gas.h" 151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic struct wpabuf * 181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtgas_build_req(u8 action, u8 dialog_token, size_t size) 191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *buf; 211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf = wpabuf_alloc(100 + size); 231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (buf == NULL) 241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC); 271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_u8(buf, action); 281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_u8(buf, dialog_token); 291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return buf; 311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 3461d9df3e62aaa0e87ad05452fcb95142159a17b6Dmitry Shmidtstruct wpabuf * gas_build_initial_req(u8 dialog_token, size_t size) 351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return gas_build_req(WLAN_PA_GAS_INITIAL_REQ, dialog_token, 371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size); 381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct wpabuf * gas_build_comeback_req(u8 dialog_token) 421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return gas_build_req(WLAN_PA_GAS_COMEBACK_REQ, dialog_token, 0); 441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic struct wpabuf * 481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtgas_build_resp(u8 action, u8 dialog_token, u16 status_code, u8 frag_id, 491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 more, u16 comeback_delay, size_t size) 501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *buf; 521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf = wpabuf_alloc(100 + size); 541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (buf == NULL) 551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_u8(buf, WLAN_ACTION_PUBLIC); 581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_u8(buf, action); 591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_u8(buf, dialog_token); 601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_le16(buf, status_code); 611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (action == WLAN_PA_GAS_COMEBACK_RESP) 621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_u8(buf, frag_id | (more ? 0x80 : 0)); 631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_le16(buf, comeback_delay); 641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return buf; 661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct wpabuf * 701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtgas_build_initial_resp(u8 dialog_token, u16 status_code, u16 comeback_delay, 711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t size) 721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return gas_build_resp(WLAN_PA_GAS_INITIAL_RESP, dialog_token, 741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt status_code, 0, 0, comeback_delay, size); 751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic struct wpabuf * 791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtgas_build_comeback_resp(u8 dialog_token, u16 status_code, u8 frag_id, u8 more, 801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 comeback_delay, size_t size) 811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return gas_build_resp(WLAN_PA_GAS_COMEBACK_RESP, dialog_token, 831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt status_code, frag_id, more, comeback_delay, 841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size); 851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/** 891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * gas_add_adv_proto_anqp - Add an Advertisement Protocol element 901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @buf: Buffer to which the element is added 911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @query_resp_len_limit: Query Response Length Limit in units of 256 octets 921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @pame_bi: Pre-Association Message Exchange BSSID Independent (0/1) 931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * 941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * 951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @query_resp_len_limit is 0 for request and 1-0x7f for response. 0x7f means 961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * that the maximum limit is determined by the maximum allowable number of 971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * fragments in the GAS Query Response Fragment ID. 981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstatic void gas_add_adv_proto_anqp(struct wpabuf *buf, u8 query_resp_len_limit, 1001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 pame_bi) 1011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 1021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Advertisement Protocol IE */ 1031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO); 1041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_u8(buf, 2); /* Length */ 1051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_u8(buf, (query_resp_len_limit & 0x7f) | 1061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt (pame_bi ? 0x80 : 0)); 1071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt /* Advertisement Protocol */ 1081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_u8(buf, ACCESS_NETWORK_QUERY_PROTOCOL); 1091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 1101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct wpabuf * gas_anqp_build_initial_req(u8 dialog_token, size_t size) 1131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 1141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *buf; 1151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf = gas_build_initial_req(dialog_token, 4 + size); 1171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (buf == NULL) 1181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 1191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt gas_add_adv_proto_anqp(buf, 0, 0); 1211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put(buf, 2); /* Query Request Length to be filled */ 1231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return buf; 1251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 1261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct wpabuf * gas_anqp_build_initial_resp(u8 dialog_token, u16 status_code, 1291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 comeback_delay, size_t size) 1301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 1311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *buf; 1321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf = gas_build_initial_resp(dialog_token, status_code, comeback_delay, 1341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 4 + size); 1351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (buf == NULL) 1361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 1371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt gas_add_adv_proto_anqp(buf, 0x7f, 0); 1391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put(buf, 2); /* Query Response Length to be filled */ 1411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return buf; 1431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 1441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct wpabuf * gas_anqp_build_initial_resp_buf(u8 dialog_token, 1471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 status_code, 1481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 comeback_delay, 1491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *payload) 1501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 1511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *buf; 1521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf = gas_anqp_build_initial_resp(dialog_token, status_code, 1541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt comeback_delay, 1551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt payload ? wpabuf_len(payload) : 0); 1561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (buf == NULL) 1571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 1581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (payload) 1601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_buf(buf, payload); 1611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt gas_anqp_set_len(buf); 1631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return buf; 1651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 1661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct wpabuf * gas_anqp_build_comeback_resp(u8 dialog_token, u16 status_code, 1691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 frag_id, u8 more, 1701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 comeback_delay, size_t size) 1711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 1721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *buf; 1731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1741f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf = gas_build_comeback_resp(dialog_token, status_code, 1751f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt frag_id, more, comeback_delay, 4 + size); 1761f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (buf == NULL) 1771f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 1781f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1791f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt gas_add_adv_proto_anqp(buf, 0x7f, 0); 1801f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1811f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put(buf, 2); /* Query Response Length to be filled */ 1821f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1831f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return buf; 1841f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 1851f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1861f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1871f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtstruct wpabuf * gas_anqp_build_comeback_resp_buf(u8 dialog_token, 1881f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 status_code, 1891f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 frag_id, u8 more, 1901f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u16 comeback_delay, 1911f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *payload) 1921f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 1931f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt struct wpabuf *buf; 1941f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 1951f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt buf = gas_anqp_build_comeback_resp(dialog_token, status_code, frag_id, 1961f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt more, comeback_delay, 1971f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt payload ? wpabuf_len(payload) : 0); 1981f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (buf == NULL) 1991f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return NULL; 2001f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2011f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (payload) 2021f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_buf(buf, payload); 2031f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2041f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt gas_anqp_set_len(buf); 2051f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2061f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return buf; 2071f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 2081f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2091f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2101f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/** 2111f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * gas_anqp_set_len - Set Query Request/Response Length 2121f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @buf: GAS message 2131f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * 2141f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * This function is used to update the Query Request/Response Length field once 2151f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * the payload has been filled. 2161f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 2171f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid gas_anqp_set_len(struct wpabuf *buf) 2181f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2191f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 action; 2201f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt size_t offset; 2211f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt u8 *len; 2221f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2231f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (buf == NULL || wpabuf_len(buf) < 2) 2241f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 2251f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2261f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt action = *(wpabuf_head_u8(buf) + 1); 2271f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt switch (action) { 2281f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case WLAN_PA_GAS_INITIAL_REQ: 2291f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt offset = 3 + 4; 2301f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 2311f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case WLAN_PA_GAS_INITIAL_RESP: 2321f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt offset = 7 + 4; 2331f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 2341f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt case WLAN_PA_GAS_COMEBACK_RESP: 2351f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt offset = 8 + 4; 2361f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt break; 2371f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt default: 2381f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 2391f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt } 2401f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2411f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt if (wpabuf_len(buf) < offset + 2) 2421f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return; 2431f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2441f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt len = wpabuf_mhead_u8(buf) + offset; 2451f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2); 2461f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 2471f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2481f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2491f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/** 2501f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * gas_anqp_add_element - Add ANQP element header 2511f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @buf: GAS message 2521f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @info_id: ANQP Info ID 2531f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * Returns: Pointer to the Length field for gas_anqp_set_element_len() 2541f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 2551f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtu8 * gas_anqp_add_element(struct wpabuf *buf, u16 info_id) 2561f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2571f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt wpabuf_put_le16(buf, info_id); 2581f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt return wpabuf_put(buf, 2); /* Length to be filled */ 2591f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 2601f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2611f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt 2621f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt/** 2631f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * gas_anqp_set_element_len - Update ANQP element Length field 2641f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @buf: GAS message 2651f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * @len_pos: Length field position from gas_anqp_add_element() 2661f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * 2671f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * This function is called after the ANQP element payload has been added to the 2681f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt * buffer. 2691f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt */ 2701f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidtvoid gas_anqp_set_element_len(struct wpabuf *buf, u8 *len_pos) 2711f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt{ 2721f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt WPA_PUT_LE16(len_pos, (u8 *) wpabuf_put(buf, 0) - len_pos - 2); 2731f69aa52ea2e0a73ac502565df8c666ee49cab6aDmitry Shmidt} 274