driver_nl80211_android.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /*
  2. * Driver interaction with Linux nl80211/cfg80211 - Android specific
  3. * Copyright (c) 2002-2014, Jouni Malinen <j@w1.fi>
  4. * Copyright (c) 2007, Johannes Berg <johannes@sipsolutions.net>
  5. * Copyright (c) 2009-2010, Atheros Communications
  6. *
  7. * This software may be distributed under the terms of the BSD license.
  8. * See README for more details.
  9. */
  10. #include "includes.h"
  11. #include <sys/ioctl.h>
  12. #include <net/if.h>
  13. #include <netlink/genl/genl.h>
  14. #include <netlink/genl/family.h>
  15. #include <netlink/genl/ctrl.h>
  16. #include <fcntl.h>
  17. #include "utils/common.h"
  18. #include "driver_nl80211.h"
  19. #include "android_drv.h"
  20. typedef struct android_wifi_priv_cmd {
  21. char *buf;
  22. int used_len;
  23. int total_len;
  24. } android_wifi_priv_cmd;
  25. static int drv_errors = 0;
  26. static void wpa_driver_send_hang_msg(struct wpa_driver_nl80211_data *drv)
  27. {
  28. drv_errors++;
  29. if (drv_errors > DRV_NUMBER_SEQUENTIAL_ERRORS) {
  30. drv_errors = 0;
  31. wpa_msg(drv->ctx, MSG_INFO, WPA_EVENT_DRIVER_STATE "HANGED");
  32. }
  33. }
  34. static int android_priv_cmd(struct i802_bss *bss, const char *cmd)
  35. {
  36. struct wpa_driver_nl80211_data *drv = bss->drv;
  37. struct ifreq ifr;
  38. android_wifi_priv_cmd priv_cmd;
  39. char buf[MAX_DRV_CMD_SIZE];
  40. int ret;
  41. os_memset(&ifr, 0, sizeof(ifr));
  42. os_memset(&priv_cmd, 0, sizeof(priv_cmd));
  43. os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
  44. os_memset(buf, 0, sizeof(buf));
  45. os_strlcpy(buf, cmd, sizeof(buf));
  46. priv_cmd.buf = buf;
  47. priv_cmd.used_len = sizeof(buf);
  48. priv_cmd.total_len = sizeof(buf);
  49. ifr.ifr_data = &priv_cmd;
  50. ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
  51. if (ret < 0) {
  52. wpa_printf(MSG_ERROR, "%s: failed to issue private commands",
  53. __func__);
  54. wpa_driver_send_hang_msg(drv);
  55. return ret;
  56. }
  57. drv_errors = 0;
  58. return 0;
  59. }
  60. int android_pno_start(struct i802_bss *bss,
  61. struct wpa_driver_scan_params *params)
  62. {
  63. struct wpa_driver_nl80211_data *drv = bss->drv;
  64. struct ifreq ifr;
  65. android_wifi_priv_cmd priv_cmd;
  66. int ret = 0, i = 0, bp;
  67. char buf[WEXT_PNO_MAX_COMMAND_SIZE];
  68. bp = WEXT_PNOSETUP_HEADER_SIZE;
  69. os_memcpy(buf, WEXT_PNOSETUP_HEADER, bp);
  70. buf[bp++] = WEXT_PNO_TLV_PREFIX;
  71. buf[bp++] = WEXT_PNO_TLV_VERSION;
  72. buf[bp++] = WEXT_PNO_TLV_SUBVERSION;
  73. buf[bp++] = WEXT_PNO_TLV_RESERVED;
  74. while (i < WEXT_PNO_AMOUNT && (size_t) i < params->num_ssids) {
  75. /* Check that there is enough space needed for 1 more SSID, the
  76. * other sections and null termination */
  77. if ((bp + WEXT_PNO_SSID_HEADER_SIZE + MAX_SSID_LEN +
  78. WEXT_PNO_NONSSID_SECTIONS_SIZE + 1) >= (int) sizeof(buf))
  79. break;
  80. wpa_hexdump_ascii(MSG_DEBUG, "For PNO Scan",
  81. params->ssids[i].ssid,
  82. params->ssids[i].ssid_len);
  83. buf[bp++] = WEXT_PNO_SSID_SECTION;
  84. buf[bp++] = params->ssids[i].ssid_len;
  85. os_memcpy(&buf[bp], params->ssids[i].ssid,
  86. params->ssids[i].ssid_len);
  87. bp += params->ssids[i].ssid_len;
  88. i++;
  89. }
  90. buf[bp++] = WEXT_PNO_SCAN_INTERVAL_SECTION;
  91. os_snprintf(&buf[bp], WEXT_PNO_SCAN_INTERVAL_LENGTH + 1, "%x",
  92. WEXT_PNO_SCAN_INTERVAL);
  93. bp += WEXT_PNO_SCAN_INTERVAL_LENGTH;
  94. buf[bp++] = WEXT_PNO_REPEAT_SECTION;
  95. os_snprintf(&buf[bp], WEXT_PNO_REPEAT_LENGTH + 1, "%x",
  96. WEXT_PNO_REPEAT);
  97. bp += WEXT_PNO_REPEAT_LENGTH;
  98. buf[bp++] = WEXT_PNO_MAX_REPEAT_SECTION;
  99. os_snprintf(&buf[bp], WEXT_PNO_MAX_REPEAT_LENGTH + 1, "%x",
  100. WEXT_PNO_MAX_REPEAT);
  101. bp += WEXT_PNO_MAX_REPEAT_LENGTH + 1;
  102. memset(&ifr, 0, sizeof(ifr));
  103. memset(&priv_cmd, 0, sizeof(priv_cmd));
  104. os_strlcpy(ifr.ifr_name, bss->ifname, IFNAMSIZ);
  105. priv_cmd.buf = buf;
  106. priv_cmd.used_len = bp;
  107. priv_cmd.total_len = bp;
  108. ifr.ifr_data = &priv_cmd;
  109. ret = ioctl(drv->global->ioctl_sock, SIOCDEVPRIVATE + 1, &ifr);
  110. if (ret < 0) {
  111. wpa_printf(MSG_ERROR, "ioctl[SIOCSIWPRIV] (pnosetup): %d",
  112. ret);
  113. wpa_driver_send_hang_msg(drv);
  114. return ret;
  115. }
  116. drv_errors = 0;
  117. return android_priv_cmd(bss, "PNOFORCE 1");
  118. }
  119. int android_pno_stop(struct i802_bss *bss)
  120. {
  121. return android_priv_cmd(bss, "PNOFORCE 0");
  122. }
  123. #ifdef ANDROID_P2P
  124. #ifdef ANDROID_P2P_STUB
  125. int wpa_driver_set_p2p_noa(void *priv, u8 count, int start, int duration)
  126. {
  127. return 0;
  128. }
  129. int wpa_driver_get_p2p_noa(void *priv, u8 *buf, size_t len)
  130. {
  131. return 0;
  132. }
  133. int wpa_driver_set_p2p_ps(void *priv, int legacy_ps, int opp_ps, int ctwindow)
  134. {
  135. return -1;
  136. }
  137. int wpa_driver_set_ap_wps_p2p_ie(void *priv, const struct wpabuf *beacon,
  138. const struct wpabuf *proberesp,
  139. const struct wpabuf *assocresp)
  140. {
  141. return 0;
  142. }
  143. #endif /* ANDROID_P2P_STUB */
  144. #endif /* ANDROID_P2P */
  145. int android_nl_socket_set_nonblocking(struct nl_handle *handle)
  146. {
  147. return fcntl(nl_socket_get_fd(handle), F_SETFL, O_NONBLOCK);
  148. }
  149. int android_genl_ctrl_resolve(struct nl_handle *handle, const char *name)
  150. {
  151. /*
  152. * Android ICS has very minimal genl_ctrl_resolve() implementation, so
  153. * need to work around that.
  154. */
  155. struct nl_cache *cache = NULL;
  156. struct genl_family *nl80211 = NULL;
  157. int id = -1;
  158. if (genl_ctrl_alloc_cache(handle, &cache) < 0) {
  159. wpa_printf(MSG_ERROR, "nl80211: Failed to allocate generic "
  160. "netlink cache");
  161. goto fail;
  162. }
  163. nl80211 = genl_ctrl_search_by_name(cache, name);
  164. if (nl80211 == NULL)
  165. goto fail;
  166. id = genl_family_get_id(nl80211);
  167. fail:
  168. if (nl80211)
  169. genl_family_put(nl80211);
  170. if (cache)
  171. nl_cache_free(cache);
  172. return id;
  173. }