scan.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /*
  2. * WPA Supplicant - Scanning
  3. * Copyright (c) 2003-2008, Jouni Malinen <j@w1.fi>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License version 2 as
  7. * published by the Free Software Foundation.
  8. *
  9. * Alternatively, this software may be distributed under the terms of BSD
  10. * license.
  11. *
  12. * See README and COPYING for more details.
  13. */
  14. #include "includes.h"
  15. #include "common.h"
  16. #include "eloop.h"
  17. #include "config.h"
  18. #include "wpa_supplicant_i.h"
  19. #include "mlme.h"
  20. #include "uuid.h"
  21. static void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s)
  22. {
  23. struct wpa_ssid *ssid;
  24. union wpa_event_data data;
  25. ssid = wpa_supplicant_get_ssid(wpa_s);
  26. if (ssid == NULL)
  27. return;
  28. if (wpa_s->current_ssid == NULL)
  29. wpa_s->current_ssid = ssid;
  30. wpa_supplicant_initiate_eapol(wpa_s);
  31. wpa_printf(MSG_DEBUG, "Already associated with a configured network - "
  32. "generating associated event");
  33. os_memset(&data, 0, sizeof(data));
  34. wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data);
  35. }
  36. static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
  37. {
  38. struct wpa_supplicant *wpa_s = eloop_ctx;
  39. struct wpa_ssid *ssid;
  40. int enabled, scan_req = 0, ret;
  41. const u8 *extra_ie = NULL;
  42. size_t extra_ie_len = 0;
  43. if (wpa_s->disconnected && !wpa_s->scan_req)
  44. return;
  45. enabled = 0;
  46. ssid = wpa_s->conf->ssid;
  47. while (ssid) {
  48. if (!ssid->disabled) {
  49. enabled++;
  50. break;
  51. }
  52. ssid = ssid->next;
  53. }
  54. if (!enabled && !wpa_s->scan_req) {
  55. wpa_printf(MSG_DEBUG, "No enabled networks - do not scan");
  56. wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
  57. return;
  58. }
  59. scan_req = wpa_s->scan_req;
  60. wpa_s->scan_req = 0;
  61. if (wpa_s->conf->ap_scan != 0 &&
  62. wpa_s->driver && os_strcmp(wpa_s->driver->name, "wired") == 0) {
  63. wpa_printf(MSG_DEBUG, "Using wired driver - overriding "
  64. "ap_scan configuration");
  65. wpa_s->conf->ap_scan = 0;
  66. }
  67. if (wpa_s->conf->ap_scan == 0) {
  68. wpa_supplicant_gen_assoc_event(wpa_s);
  69. return;
  70. }
  71. if (wpa_s->wpa_state == WPA_DISCONNECTED ||
  72. wpa_s->wpa_state == WPA_INACTIVE)
  73. wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
  74. ssid = wpa_s->conf->ssid;
  75. if (wpa_s->prev_scan_ssid != BROADCAST_SSID_SCAN) {
  76. while (ssid) {
  77. if (ssid == wpa_s->prev_scan_ssid) {
  78. ssid = ssid->next;
  79. break;
  80. }
  81. ssid = ssid->next;
  82. }
  83. }
  84. while (ssid) {
  85. if (!ssid->disabled &&
  86. (ssid->scan_ssid || wpa_s->conf->ap_scan == 2))
  87. break;
  88. ssid = ssid->next;
  89. }
  90. if (scan_req != 2 && wpa_s->conf->ap_scan == 2) {
  91. /*
  92. * ap_scan=2 mode - try to associate with each SSID instead of
  93. * scanning for each scan_ssid=1 network.
  94. */
  95. if (ssid == NULL) {
  96. wpa_printf(MSG_DEBUG, "wpa_supplicant_scan: Reached "
  97. "end of scan list - go back to beginning");
  98. wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
  99. wpa_supplicant_req_scan(wpa_s, 0, 0);
  100. return;
  101. }
  102. if (ssid->next) {
  103. /* Continue from the next SSID on the next attempt. */
  104. wpa_s->prev_scan_ssid = ssid;
  105. } else {
  106. /* Start from the beginning of the SSID list. */
  107. wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
  108. }
  109. wpa_supplicant_associate(wpa_s, NULL, ssid);
  110. return;
  111. }
  112. wpa_printf(MSG_DEBUG, "Starting AP scan (%s SSID)",
  113. ssid ? "specific": "broadcast");
  114. if (ssid) {
  115. wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
  116. ssid->ssid, ssid->ssid_len);
  117. wpa_s->prev_scan_ssid = ssid;
  118. } else
  119. wpa_s->prev_scan_ssid = BROADCAST_SSID_SCAN;
  120. if (wpa_s->scan_res_tried == 0 && wpa_s->conf->ap_scan == 1 &&
  121. !wpa_s->use_client_mlme) {
  122. wpa_s->scan_res_tried++;
  123. wpa_printf(MSG_DEBUG, "Trying to get current scan results "
  124. "first without requesting a new scan to speed up "
  125. "initial association");
  126. wpa_supplicant_event(wpa_s, EVENT_SCAN_RESULTS, NULL);
  127. return;
  128. }
  129. if (wpa_s->use_client_mlme) {
  130. ieee80211_sta_set_probe_req_ie(wpa_s, extra_ie, extra_ie_len);
  131. ret = ieee80211_sta_req_scan(wpa_s, ssid ? ssid->ssid : NULL,
  132. ssid ? ssid->ssid_len : 0);
  133. } else {
  134. wpa_drv_set_probe_req_ie(wpa_s, extra_ie, extra_ie_len);
  135. ret = wpa_drv_scan(wpa_s, ssid ? ssid->ssid : NULL,
  136. ssid ? ssid->ssid_len : 0);
  137. }
  138. if (ret) {
  139. wpa_printf(MSG_WARNING, "Failed to initiate AP scan.");
  140. wpa_supplicant_req_scan(wpa_s, 10, 0);
  141. }
  142. }
  143. /**
  144. * wpa_supplicant_req_scan - Schedule a scan for neighboring access points
  145. * @wpa_s: Pointer to wpa_supplicant data
  146. * @sec: Number of seconds after which to scan
  147. * @usec: Number of microseconds after which to scan
  148. *
  149. * This function is used to schedule a scan for neighboring access points after
  150. * the specified time.
  151. */
  152. void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec)
  153. {
  154. wpa_msg(wpa_s, MSG_DEBUG, "Setting scan request: %d sec %d usec",
  155. sec, usec);
  156. eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
  157. eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL);
  158. }
  159. /**
  160. * wpa_supplicant_cancel_scan - Cancel a scheduled scan request
  161. * @wpa_s: Pointer to wpa_supplicant data
  162. *
  163. * This function is used to cancel a scan request scheduled with
  164. * wpa_supplicant_req_scan().
  165. */
  166. void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s)
  167. {
  168. wpa_msg(wpa_s, MSG_DEBUG, "Cancelling scan request");
  169. eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
  170. }