scan.c
Go to the documentation of this file.
00001 /*
00002  * WPA Supplicant - Scanning
00003  * Copyright (c) 2003-2010, Jouni Malinen <j@w1.fi>
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License version 2 as
00007  * published by the Free Software Foundation.
00008  *
00009  * Alternatively, this software may be distributed under the terms of BSD
00010  * license.
00011  *
00012  * See README and COPYING for more details.
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 /* CONFIG_WPS */
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         /* ap_scan=2 mode - try to associate with each SSID. */
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                 /* Continue from the next SSID on the next attempt. */
00108                 wpa_s->prev_scan_ssid = ssid;
00109         } else {
00110                 /* Start from the beginning of the SSID list. */
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 /* CONFIG_WPS */
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 /* CONFIG_WPS */
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(&params, 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         /* Find the starting point from which to continue scanning */
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                  * User-initiated scan request in ap_scan == 2; scan with
00336                  * wildcard SSID.
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(&params.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                  * Optimize post-provisioning scan based on channel used
00397                  * during provisioning.
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 /* CONFIG_WPS */
00416 
00417         params.filter_ssids = wpa_supplicant_build_filter_ssids(
00418                 wpa_s->conf, &params.num_filter_ssids);
00419 
00420         ret = wpa_supplicant_trigger_scan(wpa_s, &params);
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         /* If there's at least one network that should be specifically scanned
00448          * then don't cancel the scan and reschedule.  Some drivers do
00449          * background scanning which generates frequent scan results, and that
00450          * causes the specific SSID scan to get continually pushed back and
00451          * never happen, which causes hidden APs to never get probe-scanned.
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 /* Compare function for sorting scan results. Return >0 if @b is considered
00594  * better. */
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         /* WPA/WPA2 support preferred */
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         /* privacy support preferred */
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         /* best/max rate preferred if signal level close enough XXX */
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         /* use freq for channel preference */
00632 
00633         /* all things being equal, use signal level; if signal levels are
00634          * identical, use quality values since some drivers may only report
00635          * that value and leave the signal level zero */
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 }


wpa_supplicant_node
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Jan 2 2014 11:25:14