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 
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         } 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 /* CONFIG_WPS */
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 /* CONFIG_WPS */
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(&params, 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         /* Find the starting point from which to continue scanning */
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                  * User-initiated scan request in ap_scan == 2; scan with
00335                  * wildcard SSID.
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(&params.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                  * Optimize post-provisioning scan based on channel used
00396                  * during provisioning.
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 /* CONFIG_WPS */
00415 
00416         params.filter_ssids = wpa_supplicant_build_filter_ssids(
00417                 wpa_s->conf, &params.num_filter_ssids);
00418 
00419         ret = wpa_supplicant_trigger_scan(wpa_s, &params);
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         /* If there's at least one network that should be specifically scanned
00447          * then don't cancel the scan and reschedule.  Some drivers do
00448          * background scanning which generates frequent scan results, and that
00449          * causes the specific SSID scan to get continually pushed back and
00450          * never happen, which causes hidden APs to never get probe-scanned.
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 /* Compare function for sorting scan results. Return >0 if @b is considered
00593  * better. */
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         /* WPA/WPA2 support preferred */
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         /* privacy support preferred */
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         /* best/max rate preferred if signal level close enough XXX */
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         /* use freq for channel preference */
00631 
00632         /* all things being equal, use signal level; if signal levels are
00633          * identical, use quality values since some drivers may only report
00634          * that value and leave the signal level zero */
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 }


wpa_supplicant
Author(s): Package maintained by Blaise Gassend
autogenerated on Thu Jan 2 2014 11:26:38