00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "utils/includes.h"
00016
00017 #include "utils/common.h"
00018 #include "utils/eloop.h"
00019 #include "common/ieee802_11_defs.h"
00020 #include "config.h"
00021 #include "wpa_supplicant_i.h"
00022 #include "driver_i.h"
00023 #include "mlme.h"
00024 #include "wps_supplicant.h"
00025 #include "notify.h"
00026 #include "bss.h"
00027 #include "scan.h"
00028 #include "../../src/nodes/wpa_supplicant_node.h"
00029
00030 static void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s)
00031 {
00032 struct wpa_ssid *ssid;
00033 union wpa_event_data data;
00034
00035 ssid = wpa_supplicant_get_ssid(wpa_s);
00036 if (ssid == NULL)
00037 return;
00038
00039 if (wpa_s->current_ssid == NULL) {
00040 wpa_s->current_ssid = ssid;
00041 if (wpa_s->current_ssid != NULL)
00042 wpas_notify_network_changed(wpa_s);
00043 }
00044 wpa_supplicant_initiate_eapol(wpa_s);
00045 wpa_printf(MSG_DEBUG, "Already associated with a configured network - "
00046 "generating associated event");
00047 os_memset(&data, 0, sizeof(data));
00048 wpa_supplicant_event(wpa_s, EVENT_ASSOC, &data);
00049 }
00050
00051
00052 #ifdef CONFIG_WPS
00053 static int wpas_wps_in_use(struct wpa_config *conf,
00054 enum wps_request_type *req_type)
00055 {
00056 struct wpa_ssid *ssid;
00057 int wps = 0;
00058
00059 for (ssid = conf->ssid; ssid; ssid = ssid->next) {
00060 if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS))
00061 continue;
00062
00063 wps = 1;
00064 *req_type = wpas_wps_get_req_type(ssid);
00065 if (!ssid->eap.phase1)
00066 continue;
00067
00068 if (os_strstr(ssid->eap.phase1, "pbc=1"))
00069 return 2;
00070 }
00071
00072 return wps;
00073 }
00074 #endif
00075
00076
00077 int wpa_supplicant_enabled_networks(struct wpa_config *conf)
00078 {
00079 struct wpa_ssid *ssid = conf->ssid;
00080 while (ssid) {
00081 if (!ssid->disabled)
00082 return 1;
00083 ssid = ssid->next;
00084 }
00085 return 0;
00086 }
00087
00088
00089 static void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s,
00090 struct wpa_ssid *ssid)
00091 {
00092 while (ssid) {
00093 if (!ssid->disabled)
00094 break;
00095 ssid = ssid->next;
00096 }
00097
00098
00099 if (ssid == NULL) {
00100 wpa_printf(MSG_DEBUG, "wpa_supplicant_scan: Reached "
00101 "end of scan list - go back to beginning");
00102 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
00103 wpa_supplicant_req_scan(wpa_s, 0, 0);
00104 return;
00105 }
00106 if (ssid->next) {
00107
00108 wpa_s->prev_scan_ssid = ssid;
00109 } else {
00110
00111 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
00112 }
00113 wpa_supplicant_associate(wpa_s, NULL, ssid);
00114 }
00115
00116
00117 static int int_array_len(const int *a)
00118 {
00119 int i;
00120 for (i = 0; a && a[i]; i++)
00121 ;
00122 return i;
00123 }
00124
00125
00126 static void int_array_concat(int **res, const int *a)
00127 {
00128 int reslen, alen, i;
00129 int *n;
00130
00131 reslen = int_array_len(*res);
00132 alen = int_array_len(a);
00133
00134 n = os_realloc(*res, (reslen + alen + 1) * sizeof(int));
00135 if (n == NULL) {
00136 os_free(*res);
00137 *res = NULL;
00138 return;
00139 }
00140 for (i = 0; i <= alen; i++)
00141 n[reslen + i] = a[i];
00142 *res = n;
00143 }
00144
00145
00146 static int freq_cmp(const void *a, const void *b)
00147 {
00148 int _a = *(int *) a;
00149 int _b = *(int *) b;
00150
00151 if (_a == 0)
00152 return 1;
00153 if (_b == 0)
00154 return -1;
00155 return _a - _b;
00156 }
00157
00158
00159 static void int_array_sort_unique(int *a)
00160 {
00161 int alen;
00162 int i, j;
00163
00164 if (a == NULL)
00165 return;
00166
00167 alen = int_array_len(a);
00168 qsort(a, alen, sizeof(int), freq_cmp);
00169
00170 i = 0;
00171 j = 1;
00172 while (a[i] && a[j]) {
00173 if (a[i] == a[j]) {
00174 j++;
00175 continue;
00176 }
00177 a[++i] = a[j++];
00178 }
00179 if (a[i])
00180 i++;
00181 a[i] = 0;
00182 }
00183
00184
00185 int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s,
00186 struct wpa_driver_scan_params *params)
00187 {
00188 int ret;
00189
00190 wpa_supplicant_notify_scanning(wpa_s, 1);
00191
00192 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)
00193 ret = ieee80211_sta_req_scan(wpa_s, params);
00194 else
00195 ret = wpa_drv_scan(wpa_s, params);
00196
00197 if (ret) {
00198 wpa_supplicant_notify_scanning(wpa_s, 0);
00199 wpas_notify_scan_done(wpa_s, 0);
00200 ros_scan_completed(wpa_s, 0);
00201 } else
00202 wpa_s->scan_runs++;
00203
00204 return ret;
00205 }
00206
00207
00208 static struct wpa_driver_scan_filter *
00209 wpa_supplicant_build_filter_ssids(struct wpa_config *conf, size_t *num_ssids)
00210 {
00211 struct wpa_driver_scan_filter *ssids;
00212 struct wpa_ssid *ssid;
00213 size_t count;
00214
00215 *num_ssids = 0;
00216 if (!conf->filter_ssids)
00217 return NULL;
00218
00219 for (count = 0, ssid = conf->ssid; ssid; ssid = ssid->next) {
00220 if (ssid->ssid && ssid->ssid_len)
00221 count++;
00222 }
00223 if (count == 0)
00224 return NULL;
00225 ssids = os_zalloc(count * sizeof(struct wpa_driver_scan_filter));
00226 if (ssids == NULL)
00227 return NULL;
00228
00229 for (ssid = conf->ssid; ssid; ssid = ssid->next) {
00230 if (!ssid->ssid || !ssid->ssid_len)
00231 continue;
00232 os_memcpy(ssids[*num_ssids].ssid, ssid->ssid, ssid->ssid_len);
00233 ssids[*num_ssids].ssid_len = ssid->ssid_len;
00234 (*num_ssids)++;
00235 }
00236
00237 return ssids;
00238 }
00239
00240
00241 static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
00242 {
00243 struct wpa_supplicant *wpa_s = eloop_ctx;
00244 struct wpa_ssid *ssid;
00245 int scan_req = 0, ret;
00246 struct wpabuf *wps_ie = NULL;
00247 int wps = 0;
00248 #ifdef CONFIG_WPS
00249 enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO;
00250 #endif
00251 struct wpa_driver_scan_params params;
00252 size_t max_ssids;
00253 enum wpa_states prev_state;
00254
00255 if (wpa_s->disconnected && !wpa_s->scan_req) {
00256 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
00257 return;
00258 }
00259
00260 if (!wpa_supplicant_enabled_networks(wpa_s->conf) &&
00261 !wpa_s->scan_req) {
00262 wpa_printf(MSG_DEBUG, "No enabled networks - do not scan");
00263 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
00264 return;
00265 }
00266
00267 if (wpa_s->conf->ap_scan != 0 &&
00268 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)) {
00269 wpa_printf(MSG_DEBUG, "Using wired authentication - "
00270 "overriding ap_scan configuration");
00271 wpa_s->conf->ap_scan = 0;
00272 wpas_notify_ap_scan_changed(wpa_s);
00273 }
00274
00275 if (wpa_s->conf->ap_scan == 0) {
00276 wpa_supplicant_gen_assoc_event(wpa_s);
00277 return;
00278 }
00279
00280 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) ||
00281 wpa_s->conf->ap_scan == 2)
00282 max_ssids = 1;
00283 else {
00284 max_ssids = wpa_s->max_scan_ssids;
00285 if (max_ssids > WPAS_MAX_SCAN_SSIDS)
00286 max_ssids = WPAS_MAX_SCAN_SSIDS;
00287 }
00288
00289 #ifdef CONFIG_WPS
00290 wps = wpas_wps_in_use(wpa_s->conf, &req_type);
00291 #endif
00292
00293 if ((wpa_s->scan_res_tried == 0 && wpa_s->conf->ap_scan == 1 &&
00294 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) &&
00295 wps != 2 && !wpa_s->conf->filter_ssids &&
00296 !wpa_s->connect_without_scan) ||
00297 wpa_s->more_bss_to_try) {
00298 wpa_s->scan_res_tried++;
00299 wpa_printf(MSG_DEBUG, "Trying to get current scan results "
00300 "first without requesting a new scan to speed up "
00301 "initial association");
00302 wpa_supplicant_event(wpa_s, EVENT_SCAN_RESULTS, NULL);
00303 return;
00304 }
00305
00306 scan_req = wpa_s->scan_req;
00307 wpa_s->scan_req = 0;
00308
00309 os_memset(¶ms, 0, sizeof(params));
00310
00311 prev_state = wpa_s->wpa_state;
00312 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
00313 wpa_s->wpa_state == WPA_INACTIVE)
00314 wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
00315
00316
00317 ssid = wpa_s->conf->ssid;
00318 if (wpa_s->prev_scan_ssid != WILDCARD_SSID_SCAN) {
00319 while (ssid) {
00320 if (ssid == wpa_s->prev_scan_ssid) {
00321 ssid = ssid->next;
00322 break;
00323 }
00324 ssid = ssid->next;
00325 }
00326 }
00327
00328 if (scan_req != 2 && (wpa_s->conf->ap_scan == 2 ||
00329 wpa_s->connect_without_scan)) {
00330 wpa_s->connect_without_scan = 0;
00331 wpa_supplicant_assoc_try(wpa_s, ssid);
00332 return;
00333 } else if (wpa_s->conf->ap_scan == 2) {
00334
00335
00336
00337
00338 ssid = NULL;
00339 } else {
00340 struct wpa_ssid *start = ssid, *tssid;
00341 int freqs_set = 0;
00342 if (ssid == NULL && max_ssids > 1)
00343 ssid = wpa_s->conf->ssid;
00344 while (ssid) {
00345 if (!ssid->disabled && ssid->scan_ssid) {
00346 wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
00347 ssid->ssid, ssid->ssid_len);
00348 params.ssids[params.num_ssids].ssid =
00349 ssid->ssid;
00350 params.ssids[params.num_ssids].ssid_len =
00351 ssid->ssid_len;
00352 params.num_ssids++;
00353 if (params.num_ssids + 1 >= max_ssids)
00354 break;
00355 }
00356 ssid = ssid->next;
00357 if (ssid == start)
00358 break;
00359 if (ssid == NULL && max_ssids > 1 &&
00360 start != wpa_s->conf->ssid)
00361 ssid = wpa_s->conf->ssid;
00362 }
00363
00364 for (tssid = wpa_s->conf->ssid; tssid; tssid = tssid->next) {
00365 if (tssid->disabled)
00366 continue;
00367 if ((params.freqs || !freqs_set) && tssid->scan_freq) {
00368 int_array_concat(¶ms.freqs,
00369 tssid->scan_freq);
00370 } else {
00371 os_free(params.freqs);
00372 params.freqs = NULL;
00373 }
00374 freqs_set = 1;
00375 }
00376 int_array_sort_unique(params.freqs);
00377 }
00378
00379 if (ssid) {
00380 wpa_s->prev_scan_ssid = ssid;
00381 if (max_ssids > 1) {
00382 wpa_printf(MSG_DEBUG, "Include wildcard SSID in the "
00383 "scan request");
00384 params.num_ssids++;
00385 }
00386 wpa_printf(MSG_DEBUG, "Starting AP scan for specific SSID(s)");
00387 } else {
00388 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
00389 params.num_ssids++;
00390 wpa_printf(MSG_DEBUG, "Starting AP scan for wildcard SSID");
00391 }
00392
00393 #ifdef CONFIG_WPS
00394 if (params.freqs == NULL && wpa_s->after_wps && wpa_s->wps_freq) {
00395
00396
00397
00398
00399 wpa_printf(MSG_DEBUG, "WPS: Scan only frequency %u MHz that "
00400 "was used during provisioning", wpa_s->wps_freq);
00401 params.freqs = os_zalloc(2 * sizeof(int));
00402 if (params.freqs)
00403 params.freqs[0] = wpa_s->wps_freq;
00404 wpa_s->after_wps--;
00405 }
00406
00407 if (wps) {
00408 wps_ie = wps_build_probe_req_ie(wps == 2, &wpa_s->wps->dev,
00409 wpa_s->wps->uuid, req_type);
00410 if (wps_ie) {
00411 params.extra_ies = wpabuf_head(wps_ie);
00412 params.extra_ies_len = wpabuf_len(wps_ie);
00413 }
00414 }
00415 #endif
00416
00417 params.filter_ssids = wpa_supplicant_build_filter_ssids(
00418 wpa_s->conf, ¶ms.num_filter_ssids);
00419
00420 ret = wpa_supplicant_trigger_scan(wpa_s, ¶ms);
00421
00422 wpabuf_free(wps_ie);
00423 os_free(params.freqs);
00424 os_free(params.filter_ssids);
00425
00426 if (ret) {
00427 wpa_printf(MSG_WARNING, "Failed to initiate AP scan.");
00428 if (prev_state != wpa_s->wpa_state)
00429 wpa_supplicant_set_state(wpa_s, prev_state);
00430 wpa_supplicant_req_scan(wpa_s, 1, 0);
00431 } else
00432 wpa_s->scan_runs++;
00433 }
00434
00435
00445 void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec)
00446 {
00447
00448
00449
00450
00451
00452
00453 if (eloop_is_timeout_registered(wpa_supplicant_scan, wpa_s, NULL) &&
00454 wpa_s->conf->ap_scan == 1) {
00455 struct wpa_ssid *ssid = wpa_s->conf->ssid;
00456
00457 while (ssid) {
00458 if (!ssid->disabled && ssid->scan_ssid)
00459 break;
00460 ssid = ssid->next;
00461 }
00462 if (ssid) {
00463 wpa_msg(wpa_s, MSG_DEBUG, "Not rescheduling scan to "
00464 "ensure that specific SSID scans occur");
00465 return;
00466 }
00467 }
00468
00469 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan request: %d sec %d usec",
00470 sec, usec);
00471 eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
00472 eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL);
00473 }
00474
00475
00483 void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s)
00484 {
00485 wpa_msg(wpa_s, MSG_DEBUG, "Cancelling scan request");
00486 eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
00487 }
00488
00489
00490 void wpa_supplicant_notify_scanning(struct wpa_supplicant *wpa_s,
00491 int scanning)
00492 {
00493 if (wpa_s->scanning != scanning) {
00494 wpa_s->scanning = scanning;
00495 wpas_notify_scanning(wpa_s);
00496 }
00497 }
00498
00499
00500 static int wpa_scan_get_max_rate(const struct wpa_scan_res *res)
00501 {
00502 int rate = 0;
00503 const u8 *ie;
00504 int i;
00505
00506 ie = wpa_scan_get_ie(res, WLAN_EID_SUPP_RATES);
00507 for (i = 0; ie && i < ie[1]; i++) {
00508 if ((ie[i + 2] & 0x7f) > rate)
00509 rate = ie[i + 2] & 0x7f;
00510 }
00511
00512 ie = wpa_scan_get_ie(res, WLAN_EID_EXT_SUPP_RATES);
00513 for (i = 0; ie && i < ie[1]; i++) {
00514 if ((ie[i + 2] & 0x7f) > rate)
00515 rate = ie[i + 2] & 0x7f;
00516 }
00517
00518 return rate;
00519 }
00520
00521
00522 const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie)
00523 {
00524 const u8 *end, *pos;
00525
00526 pos = (const u8 *) (res + 1);
00527 end = pos + res->ie_len;
00528
00529 while (pos + 1 < end) {
00530 if (pos + 2 + pos[1] > end)
00531 break;
00532 if (pos[0] == ie)
00533 return pos;
00534 pos += 2 + pos[1];
00535 }
00536
00537 return NULL;
00538 }
00539
00540
00541 const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res,
00542 u32 vendor_type)
00543 {
00544 const u8 *end, *pos;
00545
00546 pos = (const u8 *) (res + 1);
00547 end = pos + res->ie_len;
00548
00549 while (pos + 1 < end) {
00550 if (pos + 2 + pos[1] > end)
00551 break;
00552 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
00553 vendor_type == WPA_GET_BE32(&pos[2]))
00554 return pos;
00555 pos += 2 + pos[1];
00556 }
00557
00558 return NULL;
00559 }
00560
00561
00562 struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res,
00563 u32 vendor_type)
00564 {
00565 struct wpabuf *buf;
00566 const u8 *end, *pos;
00567
00568 buf = wpabuf_alloc(res->ie_len);
00569 if (buf == NULL)
00570 return NULL;
00571
00572 pos = (const u8 *) (res + 1);
00573 end = pos + res->ie_len;
00574
00575 while (pos + 1 < end) {
00576 if (pos + 2 + pos[1] > end)
00577 break;
00578 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
00579 vendor_type == WPA_GET_BE32(&pos[2]))
00580 wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4);
00581 pos += 2 + pos[1];
00582 }
00583
00584 if (wpabuf_len(buf) == 0) {
00585 wpabuf_free(buf);
00586 buf = NULL;
00587 }
00588
00589 return buf;
00590 }
00591
00592
00593
00594
00595 static int wpa_scan_result_compar(const void *a, const void *b)
00596 {
00597 struct wpa_scan_res **_wa = (void *) a;
00598 struct wpa_scan_res **_wb = (void *) b;
00599 struct wpa_scan_res *wa = *_wa;
00600 struct wpa_scan_res *wb = *_wb;
00601 int wpa_a, wpa_b, maxrate_a, maxrate_b;
00602
00603
00604 wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL ||
00605 wpa_scan_get_ie(wa, WLAN_EID_RSN) != NULL;
00606 wpa_b = wpa_scan_get_vendor_ie(wb, WPA_IE_VENDOR_TYPE) != NULL ||
00607 wpa_scan_get_ie(wb, WLAN_EID_RSN) != NULL;
00608
00609 if (wpa_b && !wpa_a)
00610 return 1;
00611 if (!wpa_b && wpa_a)
00612 return -1;
00613
00614
00615 if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 &&
00616 (wb->caps & IEEE80211_CAP_PRIVACY))
00617 return 1;
00618 if ((wa->caps & IEEE80211_CAP_PRIVACY) &&
00619 (wb->caps & IEEE80211_CAP_PRIVACY) == 0)
00620 return -1;
00621
00622
00623 if ((wa->level && wb->level && abs(wb->level - wa->level) < 5) ||
00624 (wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) {
00625 maxrate_a = wpa_scan_get_max_rate(wa);
00626 maxrate_b = wpa_scan_get_max_rate(wb);
00627 if (maxrate_a != maxrate_b)
00628 return maxrate_b - maxrate_a;
00629 }
00630
00631
00632
00633
00634
00635
00636 if (wb->level == wa->level)
00637 return wb->qual - wa->qual;
00638 return wb->level - wa->level;
00639 }
00640
00641
00653 struct wpa_scan_results *
00654 wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
00655 struct scan_info *info, int new_scan)
00656 {
00657 struct wpa_scan_results *scan_res;
00658 size_t i;
00659
00660 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)
00661 scan_res = ieee80211_sta_get_scan_results(wpa_s);
00662 else
00663 scan_res = wpa_drv_get_scan_results2(wpa_s);
00664 if (scan_res == NULL) {
00665 wpa_printf(MSG_DEBUG, "Failed to get scan results");
00666 return NULL;
00667 }
00668
00669 qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *),
00670 wpa_scan_result_compar);
00671
00672 wpa_bss_update_start(wpa_s);
00673 for (i = 0; i < scan_res->num; i++)
00674 wpa_bss_update_scan_res(wpa_s, scan_res->res[i]);
00675 wpa_bss_update_end(wpa_s, info, new_scan);
00676
00677 return scan_res;
00678 }
00679
00680
00681 int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s)
00682 {
00683 struct wpa_scan_results *scan_res;
00684 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
00685 if (scan_res == NULL)
00686 return -1;
00687 wpa_scan_results_free(scan_res);
00688
00689 return 0;
00690 }
00691
00692
00693 void wpa_scan_results_free(struct wpa_scan_results *res)
00694 {
00695 size_t i;
00696
00697 if (res == NULL)
00698 return;
00699
00700 for (i = 0; i < res->num; i++)
00701 os_free(res->res[i]);
00702 os_free(res->res);
00703 os_free(res);
00704 }