hs20_supplicant.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. * Copyright (c) 2009, Atheros Communications, Inc.
  3. * Copyright (c) 2011-2012, Qualcomm Atheros, Inc.
  4. *
  5. * This software may be distributed under the terms of the BSD license.
  6. * See README for more details.
  7. */
  8. #include "includes.h"
  9. #include "common.h"
  10. #include "eloop.h"
  11. #include "common/ieee802_11_common.h"
  12. #include "common/ieee802_11_defs.h"
  13. #include "common/gas.h"
  14. #include "common/wpa_ctrl.h"
  15. #include "wpa_supplicant_i.h"
  16. #include "driver_i.h"
  17. #include "config.h"
  18. #include "bss.h"
  19. #include "gas_query.h"
  20. #include "interworking.h"
  21. #include "hs20_supplicant.h"
  22. struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload,
  23. size_t payload_len)
  24. {
  25. struct wpabuf *buf;
  26. u8 *len_pos;
  27. buf = gas_anqp_build_initial_req(0, 100 + payload_len);
  28. if (buf == NULL)
  29. return NULL;
  30. len_pos = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
  31. wpabuf_put_be24(buf, OUI_WFA);
  32. wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
  33. if (stypes == BIT(HS20_STYPE_NAI_HOME_REALM_QUERY)) {
  34. wpabuf_put_u8(buf, HS20_STYPE_NAI_HOME_REALM_QUERY);
  35. wpabuf_put_u8(buf, 0); /* Reserved */
  36. if (payload)
  37. wpabuf_put_data(buf, payload, payload_len);
  38. } else {
  39. u8 i;
  40. wpabuf_put_u8(buf, HS20_STYPE_QUERY_LIST);
  41. wpabuf_put_u8(buf, 0); /* Reserved */
  42. for (i = 0; i < 32; i++) {
  43. if (stypes & BIT(i))
  44. wpabuf_put_u8(buf, i);
  45. }
  46. }
  47. gas_anqp_set_element_len(buf, len_pos);
  48. gas_anqp_set_len(buf);
  49. return buf;
  50. }
  51. int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes,
  52. const u8 *payload, size_t payload_len)
  53. {
  54. struct wpabuf *buf;
  55. int ret = 0;
  56. int freq;
  57. struct wpa_bss *bss;
  58. int res;
  59. freq = wpa_s->assoc_freq;
  60. bss = wpa_bss_get_bssid(wpa_s, dst);
  61. if (bss)
  62. freq = bss->freq;
  63. if (freq <= 0)
  64. return -1;
  65. wpa_printf(MSG_DEBUG, "HS20: ANQP Query Request to " MACSTR " for "
  66. "subtypes 0x%x", MAC2STR(dst), stypes);
  67. buf = hs20_build_anqp_req(stypes, payload, payload_len);
  68. if (buf == NULL)
  69. return -1;
  70. res = gas_query_req(wpa_s->gas, dst, freq, buf, anqp_resp_cb, wpa_s);
  71. if (res < 0) {
  72. wpa_printf(MSG_DEBUG, "ANQP: Failed to send Query Request");
  73. ret = -1;
  74. } else
  75. wpa_printf(MSG_DEBUG, "ANQP: Query started with dialog token "
  76. "%u", res);
  77. wpabuf_free(buf);
  78. return ret;
  79. }
  80. void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s,
  81. const u8 *sa, const u8 *data, size_t slen)
  82. {
  83. const u8 *pos = data;
  84. u8 subtype;
  85. struct wpa_bss *bss = wpa_bss_get_bssid(wpa_s, sa);
  86. if (slen < 2)
  87. return;
  88. subtype = *pos++;
  89. slen--;
  90. pos++; /* Reserved */
  91. slen--;
  92. switch (subtype) {
  93. case HS20_STYPE_CAPABILITY_LIST:
  94. wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
  95. " HS Capability List", MAC2STR(sa));
  96. wpa_hexdump_ascii(MSG_DEBUG, "HS Capability List", pos, slen);
  97. break;
  98. case HS20_STYPE_OPERATOR_FRIENDLY_NAME:
  99. wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
  100. " Operator Friendly Name", MAC2STR(sa));
  101. wpa_hexdump_ascii(MSG_DEBUG, "oper friendly name", pos, slen);
  102. if (bss) {
  103. wpabuf_free(bss->hs20_operator_friendly_name);
  104. bss->hs20_operator_friendly_name =
  105. wpabuf_alloc_copy(pos, slen);
  106. }
  107. break;
  108. case HS20_STYPE_WAN_METRICS:
  109. wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
  110. " WAN Metrics", MAC2STR(sa));
  111. wpa_hexdump_ascii(MSG_DEBUG, "WAN Metrics", pos, slen);
  112. if (bss) {
  113. wpabuf_free(bss->hs20_wan_metrics);
  114. bss->hs20_wan_metrics = wpabuf_alloc_copy(pos, slen);
  115. }
  116. break;
  117. case HS20_STYPE_CONNECTION_CAPABILITY:
  118. wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
  119. " Connection Capability", MAC2STR(sa));
  120. wpa_hexdump_ascii(MSG_DEBUG, "conn capability", pos, slen);
  121. if (bss) {
  122. wpabuf_free(bss->hs20_connection_capability);
  123. bss->hs20_connection_capability =
  124. wpabuf_alloc_copy(pos, slen);
  125. }
  126. break;
  127. case HS20_STYPE_OPERATING_CLASS:
  128. wpa_msg(wpa_s, MSG_INFO, "RX-HS20-ANQP " MACSTR
  129. " Operating Class", MAC2STR(sa));
  130. wpa_hexdump_ascii(MSG_DEBUG, "Operating Class", pos, slen);
  131. if (bss) {
  132. wpabuf_free(bss->hs20_operating_class);
  133. bss->hs20_operating_class =
  134. wpabuf_alloc_copy(pos, slen);
  135. }
  136. break;
  137. default:
  138. wpa_printf(MSG_DEBUG, "HS20: Unsupported subtype %u", subtype);
  139. break;
  140. }
  141. }