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
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 } else
00201 wpa_s->scan_runs++;
00202
00203 return ret;
00204 }
00205
00206
00207 static struct wpa_driver_scan_filter *
00208 wpa_supplicant_build_filter_ssids(struct wpa_config *conf, size_t *num_ssids)
00209 {
00210 struct wpa_driver_scan_filter *ssids;
00211 struct wpa_ssid *ssid;
00212 size_t count;
00213
00214 *num_ssids = 0;
00215 if (!conf->filter_ssids)
00216 return NULL;
00217
00218 for (count = 0, ssid = conf->ssid; ssid; ssid = ssid->next) {
00219 if (ssid->ssid && ssid->ssid_len)
00220 count++;
00221 }
00222 if (count == 0)
00223 return NULL;
00224 ssids = os_zalloc(count * sizeof(struct wpa_driver_scan_filter));
00225 if (ssids == NULL)
00226 return NULL;
00227
00228 for (ssid = conf->ssid; ssid; ssid = ssid->next) {
00229 if (!ssid->ssid || !ssid->ssid_len)
00230 continue;
00231 os_memcpy(ssids[*num_ssids].ssid, ssid->ssid, ssid->ssid_len);
00232 ssids[*num_ssids].ssid_len = ssid->ssid_len;
00233 (*num_ssids)++;
00234 }
00235
00236 return ssids;
00237 }
00238
00239
00240 static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx)
00241 {
00242 struct wpa_supplicant *wpa_s = eloop_ctx;
00243 struct wpa_ssid *ssid;
00244 int scan_req = 0, ret;
00245 struct wpabuf *wps_ie = NULL;
00246 int wps = 0;
00247 #ifdef CONFIG_WPS
00248 enum wps_request_type req_type = WPS_REQ_ENROLLEE_INFO;
00249 #endif
00250 struct wpa_driver_scan_params params;
00251 size_t max_ssids;
00252 enum wpa_states prev_state;
00253
00254 if (wpa_s->disconnected && !wpa_s->scan_req) {
00255 wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED);
00256 return;
00257 }
00258
00259 if (!wpa_supplicant_enabled_networks(wpa_s->conf) &&
00260 !wpa_s->scan_req) {
00261 wpa_printf(MSG_DEBUG, "No enabled networks - do not scan");
00262 wpa_supplicant_set_state(wpa_s, WPA_INACTIVE);
00263 return;
00264 }
00265
00266 if (wpa_s->conf->ap_scan != 0 &&
00267 (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)) {
00268 wpa_printf(MSG_DEBUG, "Using wired authentication - "
00269 "overriding ap_scan configuration");
00270 wpa_s->conf->ap_scan = 0;
00271 wpas_notify_ap_scan_changed(wpa_s);
00272 }
00273
00274 if (wpa_s->conf->ap_scan == 0) {
00275 wpa_supplicant_gen_assoc_event(wpa_s);
00276 return;
00277 }
00278
00279 if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) ||
00280 wpa_s->conf->ap_scan == 2)
00281 max_ssids = 1;
00282 else {
00283 max_ssids = wpa_s->max_scan_ssids;
00284 if (max_ssids > WPAS_MAX_SCAN_SSIDS)
00285 max_ssids = WPAS_MAX_SCAN_SSIDS;
00286 }
00287
00288 #ifdef CONFIG_WPS
00289 wps = wpas_wps_in_use(wpa_s->conf, &req_type);
00290 #endif
00291
00292 if ((wpa_s->scan_res_tried == 0 && wpa_s->conf->ap_scan == 1 &&
00293 !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME) &&
00294 wps != 2 && !wpa_s->conf->filter_ssids &&
00295 !wpa_s->connect_without_scan) ||
00296 wpa_s->more_bss_to_try) {
00297 wpa_s->scan_res_tried++;
00298 wpa_printf(MSG_DEBUG, "Trying to get current scan results "
00299 "first without requesting a new scan to speed up "
00300 "initial association");
00301 wpa_supplicant_event(wpa_s, EVENT_SCAN_RESULTS, NULL);
00302 return;
00303 }
00304
00305 scan_req = wpa_s->scan_req;
00306 wpa_s->scan_req = 0;
00307
00308 os_memset(¶ms, 0, sizeof(params));
00309
00310 prev_state = wpa_s->wpa_state;
00311 if (wpa_s->wpa_state == WPA_DISCONNECTED ||
00312 wpa_s->wpa_state == WPA_INACTIVE)
00313 wpa_supplicant_set_state(wpa_s, WPA_SCANNING);
00314
00315
00316 ssid = wpa_s->conf->ssid;
00317 if (wpa_s->prev_scan_ssid != WILDCARD_SSID_SCAN) {
00318 while (ssid) {
00319 if (ssid == wpa_s->prev_scan_ssid) {
00320 ssid = ssid->next;
00321 break;
00322 }
00323 ssid = ssid->next;
00324 }
00325 }
00326
00327 if (scan_req != 2 && (wpa_s->conf->ap_scan == 2 ||
00328 wpa_s->connect_without_scan)) {
00329 wpa_s->connect_without_scan = 0;
00330 wpa_supplicant_assoc_try(wpa_s, ssid);
00331 return;
00332 } else if (wpa_s->conf->ap_scan == 2) {
00333
00334
00335
00336
00337 ssid = NULL;
00338 } else {
00339 struct wpa_ssid *start = ssid, *tssid;
00340 int freqs_set = 0;
00341 if (ssid == NULL && max_ssids > 1)
00342 ssid = wpa_s->conf->ssid;
00343 while (ssid) {
00344 if (!ssid->disabled && ssid->scan_ssid) {
00345 wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID",
00346 ssid->ssid, ssid->ssid_len);
00347 params.ssids[params.num_ssids].ssid =
00348 ssid->ssid;
00349 params.ssids[params.num_ssids].ssid_len =
00350 ssid->ssid_len;
00351 params.num_ssids++;
00352 if (params.num_ssids + 1 >= max_ssids)
00353 break;
00354 }
00355 ssid = ssid->next;
00356 if (ssid == start)
00357 break;
00358 if (ssid == NULL && max_ssids > 1 &&
00359 start != wpa_s->conf->ssid)
00360 ssid = wpa_s->conf->ssid;
00361 }
00362
00363 for (tssid = wpa_s->conf->ssid; tssid; tssid = tssid->next) {
00364 if (tssid->disabled)
00365 continue;
00366 if ((params.freqs || !freqs_set) && tssid->scan_freq) {
00367 int_array_concat(¶ms.freqs,
00368 tssid->scan_freq);
00369 } else {
00370 os_free(params.freqs);
00371 params.freqs = NULL;
00372 }
00373 freqs_set = 1;
00374 }
00375 int_array_sort_unique(params.freqs);
00376 }
00377
00378 if (ssid) {
00379 wpa_s->prev_scan_ssid = ssid;
00380 if (max_ssids > 1) {
00381 wpa_printf(MSG_DEBUG, "Include wildcard SSID in the "
00382 "scan request");
00383 params.num_ssids++;
00384 }
00385 wpa_printf(MSG_DEBUG, "Starting AP scan for specific SSID(s)");
00386 } else {
00387 wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN;
00388 params.num_ssids++;
00389 wpa_printf(MSG_DEBUG, "Starting AP scan for wildcard SSID");
00390 }
00391
00392 #ifdef CONFIG_WPS
00393 if (params.freqs == NULL && wpa_s->after_wps && wpa_s->wps_freq) {
00394
00395
00396
00397
00398 wpa_printf(MSG_DEBUG, "WPS: Scan only frequency %u MHz that "
00399 "was used during provisioning", wpa_s->wps_freq);
00400 params.freqs = os_zalloc(2 * sizeof(int));
00401 if (params.freqs)
00402 params.freqs[0] = wpa_s->wps_freq;
00403 wpa_s->after_wps--;
00404 }
00405
00406 if (wps) {
00407 wps_ie = wps_build_probe_req_ie(wps == 2, &wpa_s->wps->dev,
00408 wpa_s->wps->uuid, req_type);
00409 if (wps_ie) {
00410 params.extra_ies = wpabuf_head(wps_ie);
00411 params.extra_ies_len = wpabuf_len(wps_ie);
00412 }
00413 }
00414 #endif
00415
00416 params.filter_ssids = wpa_supplicant_build_filter_ssids(
00417 wpa_s->conf, ¶ms.num_filter_ssids);
00418
00419 ret = wpa_supplicant_trigger_scan(wpa_s, ¶ms);
00420
00421 wpabuf_free(wps_ie);
00422 os_free(params.freqs);
00423 os_free(params.filter_ssids);
00424
00425 if (ret) {
00426 wpa_printf(MSG_WARNING, "Failed to initiate AP scan.");
00427 if (prev_state != wpa_s->wpa_state)
00428 wpa_supplicant_set_state(wpa_s, prev_state);
00429 wpa_supplicant_req_scan(wpa_s, 1, 0);
00430 } else
00431 wpa_s->scan_runs++;
00432 }
00433
00434
00444 void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec)
00445 {
00446
00447
00448
00449
00450
00451
00452 if (eloop_is_timeout_registered(wpa_supplicant_scan, wpa_s, NULL) &&
00453 wpa_s->conf->ap_scan == 1) {
00454 struct wpa_ssid *ssid = wpa_s->conf->ssid;
00455
00456 while (ssid) {
00457 if (!ssid->disabled && ssid->scan_ssid)
00458 break;
00459 ssid = ssid->next;
00460 }
00461 if (ssid) {
00462 wpa_msg(wpa_s, MSG_DEBUG, "Not rescheduling scan to "
00463 "ensure that specific SSID scans occur");
00464 return;
00465 }
00466 }
00467
00468 wpa_msg(wpa_s, MSG_DEBUG, "Setting scan request: %d sec %d usec",
00469 sec, usec);
00470 eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
00471 eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL);
00472 }
00473
00474
00482 void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s)
00483 {
00484 wpa_msg(wpa_s, MSG_DEBUG, "Cancelling scan request");
00485 eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL);
00486 }
00487
00488
00489 void wpa_supplicant_notify_scanning(struct wpa_supplicant *wpa_s,
00490 int scanning)
00491 {
00492 if (wpa_s->scanning != scanning) {
00493 wpa_s->scanning = scanning;
00494 wpas_notify_scanning(wpa_s);
00495 }
00496 }
00497
00498
00499 static int wpa_scan_get_max_rate(const struct wpa_scan_res *res)
00500 {
00501 int rate = 0;
00502 const u8 *ie;
00503 int i;
00504
00505 ie = wpa_scan_get_ie(res, WLAN_EID_SUPP_RATES);
00506 for (i = 0; ie && i < ie[1]; i++) {
00507 if ((ie[i + 2] & 0x7f) > rate)
00508 rate = ie[i + 2] & 0x7f;
00509 }
00510
00511 ie = wpa_scan_get_ie(res, WLAN_EID_EXT_SUPP_RATES);
00512 for (i = 0; ie && i < ie[1]; i++) {
00513 if ((ie[i + 2] & 0x7f) > rate)
00514 rate = ie[i + 2] & 0x7f;
00515 }
00516
00517 return rate;
00518 }
00519
00520
00521 const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie)
00522 {
00523 const u8 *end, *pos;
00524
00525 pos = (const u8 *) (res + 1);
00526 end = pos + res->ie_len;
00527
00528 while (pos + 1 < end) {
00529 if (pos + 2 + pos[1] > end)
00530 break;
00531 if (pos[0] == ie)
00532 return pos;
00533 pos += 2 + pos[1];
00534 }
00535
00536 return NULL;
00537 }
00538
00539
00540 const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res,
00541 u32 vendor_type)
00542 {
00543 const u8 *end, *pos;
00544
00545 pos = (const u8 *) (res + 1);
00546 end = pos + res->ie_len;
00547
00548 while (pos + 1 < end) {
00549 if (pos + 2 + pos[1] > end)
00550 break;
00551 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
00552 vendor_type == WPA_GET_BE32(&pos[2]))
00553 return pos;
00554 pos += 2 + pos[1];
00555 }
00556
00557 return NULL;
00558 }
00559
00560
00561 struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res,
00562 u32 vendor_type)
00563 {
00564 struct wpabuf *buf;
00565 const u8 *end, *pos;
00566
00567 buf = wpabuf_alloc(res->ie_len);
00568 if (buf == NULL)
00569 return NULL;
00570
00571 pos = (const u8 *) (res + 1);
00572 end = pos + res->ie_len;
00573
00574 while (pos + 1 < end) {
00575 if (pos + 2 + pos[1] > end)
00576 break;
00577 if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 &&
00578 vendor_type == WPA_GET_BE32(&pos[2]))
00579 wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4);
00580 pos += 2 + pos[1];
00581 }
00582
00583 if (wpabuf_len(buf) == 0) {
00584 wpabuf_free(buf);
00585 buf = NULL;
00586 }
00587
00588 return buf;
00589 }
00590
00591
00592
00593
00594 static int wpa_scan_result_compar(const void *a, const void *b)
00595 {
00596 struct wpa_scan_res **_wa = (void *) a;
00597 struct wpa_scan_res **_wb = (void *) b;
00598 struct wpa_scan_res *wa = *_wa;
00599 struct wpa_scan_res *wb = *_wb;
00600 int wpa_a, wpa_b, maxrate_a, maxrate_b;
00601
00602
00603 wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL ||
00604 wpa_scan_get_ie(wa, WLAN_EID_RSN) != NULL;
00605 wpa_b = wpa_scan_get_vendor_ie(wb, WPA_IE_VENDOR_TYPE) != NULL ||
00606 wpa_scan_get_ie(wb, WLAN_EID_RSN) != NULL;
00607
00608 if (wpa_b && !wpa_a)
00609 return 1;
00610 if (!wpa_b && wpa_a)
00611 return -1;
00612
00613
00614 if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 &&
00615 (wb->caps & IEEE80211_CAP_PRIVACY))
00616 return 1;
00617 if ((wa->caps & IEEE80211_CAP_PRIVACY) &&
00618 (wb->caps & IEEE80211_CAP_PRIVACY) == 0)
00619 return -1;
00620
00621
00622 if ((wa->level && wb->level && abs(wb->level - wa->level) < 5) ||
00623 (wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) {
00624 maxrate_a = wpa_scan_get_max_rate(wa);
00625 maxrate_b = wpa_scan_get_max_rate(wb);
00626 if (maxrate_a != maxrate_b)
00627 return maxrate_b - maxrate_a;
00628 }
00629
00630
00631
00632
00633
00634
00635 if (wb->level == wa->level)
00636 return wb->qual - wa->qual;
00637 return wb->level - wa->level;
00638 }
00639
00640
00652 struct wpa_scan_results *
00653 wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s,
00654 struct scan_info *info, int new_scan)
00655 {
00656 struct wpa_scan_results *scan_res;
00657 size_t i;
00658
00659 if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_USER_SPACE_MLME)
00660 scan_res = ieee80211_sta_get_scan_results(wpa_s);
00661 else
00662 scan_res = wpa_drv_get_scan_results2(wpa_s);
00663 if (scan_res == NULL) {
00664 wpa_printf(MSG_DEBUG, "Failed to get scan results");
00665 return NULL;
00666 }
00667
00668 qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *),
00669 wpa_scan_result_compar);
00670
00671 wpa_bss_update_start(wpa_s);
00672 for (i = 0; i < scan_res->num; i++)
00673 wpa_bss_update_scan_res(wpa_s, scan_res->res[i]);
00674 wpa_bss_update_end(wpa_s, info, new_scan);
00675
00676 return scan_res;
00677 }
00678
00679
00680 int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s)
00681 {
00682 struct wpa_scan_results *scan_res;
00683 scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0);
00684 if (scan_res == NULL)
00685 return -1;
00686 wpa_scan_results_free(scan_res);
00687
00688 return 0;
00689 }
00690
00691
00692 void wpa_scan_results_free(struct wpa_scan_results *res)
00693 {
00694 size_t i;
00695
00696 if (res == NULL)
00697 return;
00698
00699 for (i = 0; i < res->num; i++)
00700 os_free(res->res[i]);
00701 os_free(res->res);
00702 os_free(res);
00703 }