Home | History | Annotate | Download | only in lib
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 /*-------------------------------------------------------------------*/
     17 #include "includes.h"
     18 #include "scanmerge.h"
     19 #include "shlist.h"
     20 
     21 #define IS_HIDDEN_AP(a)	(((a)->ssid_len == 0) || ((a)->ssid[0] == '\0'))
     22 
     23 scan_ssid_t *scan_get_ssid( scan_result_t *res_ptr )
     24 {
     25     static scan_ssid_t ssid_temp;
     26 #ifdef WPA_SUPPLICANT_VER_0_6_X
     27     const u8 *res_ie;
     28 
     29     res_ie = wpa_scan_get_ie(res_ptr, WLAN_EID_SSID);
     30     if (!res_ie)
     31         return NULL;
     32     ssid_temp.ssid_len = (size_t)res_ie[1];
     33     os_memcpy(ssid_temp.ssid, (res_ie + 2), ssid_temp.ssid_len);
     34 #else
     35     ssid_temp.ssid_len = res_ptr->ssid_len;
     36     os_memcpy(ssid_temp.ssid, res_ptr->ssid, ssid_temp.ssid_len);
     37 #endif
     38     return &ssid_temp;
     39 }
     40 
     41 /*-----------------------------------------------------------------------------
     42 Routine Name: scan_init
     43 Routine Description: Inits scan merge list
     44 Arguments:
     45    mydrv   - pointer to private driver data structure
     46 Return Value:
     47 -----------------------------------------------------------------------------*/
     48 void scan_init( struct wpa_driver_ti_data *mydrv )
     49 {
     50     mydrv->last_scan = -1;
     51     shListInitList(&(mydrv->scan_merge_list));
     52 }
     53 
     54 /*-----------------------------------------------------------------------------
     55 Routine Name: scan_free
     56 Routine Description: Frees scan structure private data
     57 Arguments:
     58    ptr - pointer to private data structure
     59 Return Value:
     60 -----------------------------------------------------------------------------*/
     61 static void scan_free( void *ptr )
     62 {
     63     os_free(ptr);
     64 }
     65 
     66 /*-----------------------------------------------------------------------------
     67 Routine Name: scan_exit
     68 Routine Description: Cleans scan merge list
     69 Arguments:
     70    mydrv   - pointer to private driver data structure
     71 Return Value:
     72 -----------------------------------------------------------------------------*/
     73 void scan_exit( struct wpa_driver_ti_data *mydrv )
     74 {
     75     shListDelAllItems(&(mydrv->scan_merge_list), scan_free);
     76 }
     77 
     78 /*-----------------------------------------------------------------------------
     79 Routine Name: scan_count
     80 Routine Description: Gives number of list elements
     81 Arguments:
     82    mydrv   - pointer to private driver data structure
     83 Return Value: Number of elements in the list
     84 -----------------------------------------------------------------------------*/
     85 unsigned long scan_count( struct wpa_driver_ti_data *mydrv )
     86 {
     87     return shListGetCount(&(mydrv->scan_merge_list));
     88 }
     89 
     90 /*-----------------------------------------------------------------------------
     91 Routine Name: scan_equal
     92 Routine Description: Compares bssid of scan result and scan merge structure
     93 Arguments:
     94    val   - pointer to scan result structure
     95    idata - pointer to scan merge structure
     96 Return Value: 1 - if equal, 0 - if not
     97 -----------------------------------------------------------------------------*/
     98 static int scan_equal( void *val,  void *idata )
     99 {
    100     scan_ssid_t n_ssid, l_ssid, *p_ssid;
    101     scan_result_t *new_res = (scan_result_t *)val;
    102     scan_result_t *lst_res =
    103                (scan_result_t *)(&(((scan_merge_t *)idata)->scanres));
    104     int ret;
    105     size_t len;
    106 
    107     p_ssid = scan_get_ssid(new_res);
    108     if (!p_ssid)
    109         return 0;
    110     os_memcpy(&n_ssid, p_ssid, sizeof(scan_ssid_t));
    111     p_ssid = scan_get_ssid(lst_res);
    112     if (!p_ssid)
    113         return 0;
    114     os_memcpy(&l_ssid, p_ssid, sizeof(scan_ssid_t));
    115 
    116     len = (IS_HIDDEN_AP(&n_ssid) || IS_HIDDEN_AP(&l_ssid)) ?
    117           0 : n_ssid.ssid_len;
    118     ret = ((l_ssid.ssid_len != n_ssid.ssid_len) && (len != 0)) ||
    119           (os_memcmp(new_res->bssid, lst_res->bssid, ETH_ALEN) ||
    120            os_memcmp(n_ssid.ssid, l_ssid.ssid, len));
    121     return !ret;
    122 }
    123 
    124 /*-----------------------------------------------------------------------------
    125 Routine Name: copy_scan_res
    126 Routine Description: copies scan result structure to scan merge list item
    127 Arguments:
    128    dst - pointer to scan result structure in the list
    129    src - source pointer to scan result structure
    130 Return Value: NONE
    131 -----------------------------------------------------------------------------*/
    132 void copy_scan_res( scan_result_t *dst, scan_result_t *src )
    133 {
    134 #ifdef WPA_SUPPLICANT_VER_0_5_X
    135     if( IS_HIDDEN_AP(src) ) {
    136         os_memcpy(src->ssid, dst->ssid, dst->ssid_len);
    137         src->ssid_len = dst->ssid_len;
    138     }
    139 #endif
    140     os_memcpy(dst, src, sizeof(scan_result_t));
    141 }
    142 
    143 /*-----------------------------------------------------------------------------
    144 Routine Name: scan_add
    145 Routine Description: adds scan result structure to scan merge list
    146 Arguments:
    147    head    - pointer to scan merge list head
    148    res_ptr - pointer to scan result structure
    149 Return Value: Pointer to scan merge item
    150 -----------------------------------------------------------------------------*/
    151 static scan_merge_t *scan_add( SHLIST *head, scan_result_t *res_ptr )
    152 {
    153     scan_merge_t *scan_ptr;
    154     unsigned size = 0;
    155 
    156 #ifdef WPA_SUPPLICANT_VER_0_6_X
    157     size += res_ptr->ie_len;
    158 #endif
    159     scan_ptr = (scan_merge_t *)os_malloc(sizeof(scan_merge_t) + size);
    160     if( !scan_ptr )
    161         return( NULL );
    162     os_memcpy(&(scan_ptr->scanres), res_ptr, sizeof(scan_result_t) + size);
    163     scan_ptr->count = SCAN_MERGE_COUNT;
    164     shListInsLastItem(head, (void *)scan_ptr);
    165     return scan_ptr;
    166 }
    167 
    168 /*-----------------------------------------------------------------------------
    169 Routine Name: scan_find
    170 Routine Description: Looks for scan merge item in scan results array
    171 Arguments:
    172    scan_ptr - pointer to scan merge item
    173    results - pointer to scan results array
    174    number_items - current number of items
    175 Return Value: 1 - if item was found, 0 - otherwise
    176 -----------------------------------------------------------------------------*/
    177 static int scan_find( scan_merge_t *scan_ptr, scan_result_t *results,
    178                       unsigned int number_items )
    179 {
    180     unsigned int i;
    181 
    182     for(i=0;( i < number_items );i++) {
    183         if( scan_equal(&(results[i]), scan_ptr) )
    184             return 1;
    185     }
    186     return 0;
    187 }
    188 
    189 #ifdef WPA_SUPPLICANT_VER_0_6_X
    190 /*-----------------------------------------------------------------------------
    191 Routine Name: scan_dup
    192 Routine Description: Create copy of scan results entry
    193 Arguments:
    194    res_ptr - pointer to scan result item
    195 Return Value: pointer to new scan result item, or NULL
    196 -----------------------------------------------------------------------------*/
    197 static scan_result_t *scan_dup( scan_result_t *res_ptr )
    198 {
    199     unsigned size;
    200     scan_result_t *new_ptr;
    201 
    202     if (!res_ptr)
    203         return NULL;
    204 
    205     size = sizeof(scan_result_t) + res_ptr->ie_len;
    206     new_ptr = os_malloc(size);
    207     if (!new_ptr)
    208         return NULL;
    209     if (res_ptr) {
    210         os_memcpy(new_ptr, res_ptr, size);
    211     }
    212     return new_ptr;
    213 }
    214 #endif
    215 
    216 /*-----------------------------------------------------------------------------
    217 Routine Name: scan_merge
    218 Routine Description: Merges current scan results with previous
    219 Arguments:
    220    mydrv   - pointer to private driver data structure
    221    results - pointer to scan results array
    222    number_items - current number of items
    223    max_size - maximum namber of items
    224 Return Value: Merged number of items
    225 -----------------------------------------------------------------------------*/
    226 #ifdef WPA_SUPPLICANT_VER_0_6_X
    227 unsigned int scan_merge( struct wpa_driver_ti_data *mydrv,
    228                          scan_result_t **results, int force_flag,
    229                          unsigned int number_items, unsigned int max_size )
    230 #else
    231 unsigned int scan_merge( struct wpa_driver_ti_data *mydrv,
    232                          scan_result_t *results, int force_flag,
    233                          unsigned int number_items, unsigned int max_size )
    234 #endif
    235 {
    236     SHLIST *head = &(mydrv->scan_merge_list);
    237     SHLIST *item, *del_item;
    238     scan_result_t *res_ptr;
    239     scan_merge_t *scan_ptr;
    240     unsigned int i;
    241 
    242     /* Prepare items for removal */
    243     item = shListGetFirstItem(head);
    244     while( item != NULL ) {
    245         scan_ptr = (scan_merge_t *)(item->data);
    246         if( scan_ptr->count != 0 )
    247             scan_ptr->count--;
    248         item = shListGetNextItem(head, item);
    249     }
    250 
    251     for(i=0;( i < number_items );i++) { /* Find/Add new items */
    252 #ifdef WPA_SUPPLICANT_VER_0_6_X
    253         res_ptr = results[i];
    254 #else
    255         res_ptr = &(results[i]);
    256 #endif
    257         item = shListFindItem( head, res_ptr, scan_equal );
    258         if( item ) {
    259 #ifdef WPA_SUPPLICANT_VER_0_6_X
    260             scan_ssid_t *p_ssid;
    261             scan_result_t *new_ptr;
    262 #endif
    263             scan_ptr = (scan_merge_t *)(item->data);
    264             copy_scan_res(&(scan_ptr->scanres), res_ptr);
    265             scan_ptr->count = SCAN_MERGE_COUNT;
    266 #ifdef WPA_SUPPLICANT_VER_0_6_X
    267 	    p_ssid = scan_get_ssid(res_ptr);
    268             if (p_ssid && IS_HIDDEN_AP(p_ssid)) {
    269                 new_ptr = scan_dup(res_ptr);
    270                 if (new_ptr) {
    271                     results[i] = new_ptr;
    272                     os_free(res_ptr);
    273                 }
    274             }
    275 #endif
    276         }
    277         else {
    278             scan_add(head, res_ptr);
    279         }
    280     }
    281 
    282     item = shListGetFirstItem( head );  /* Add/Remove missing items */
    283     while( item != NULL ) {
    284         del_item = NULL;
    285         scan_ptr = (scan_merge_t *)(item->data);
    286         if( scan_ptr->count != SCAN_MERGE_COUNT ) {
    287             if( !force_flag && ((scan_ptr->count == 0) ||
    288                 (mydrv->last_scan == SCAN_TYPE_NORMAL_ACTIVE)) ) {
    289                 del_item = item;
    290             }
    291             else {
    292                 if( number_items < max_size ) {
    293 #ifdef WPA_SUPPLICANT_VER_0_6_X
    294                     res_ptr = scan_dup(&(scan_ptr->scanres));
    295                     if (res_ptr) {
    296                         results[number_items] = res_ptr;
    297                         number_items++;
    298                     }
    299 #else
    300                     os_memcpy(&(results[number_items]),
    301                           &(scan_ptr->scanres), sizeof(scan_result_t));
    302                     number_items++;
    303 #endif
    304                 }
    305             }
    306         }
    307         item = shListGetNextItem(head, item);
    308         shListDelItem(head, del_item, scan_free);
    309     }
    310 
    311     return( number_items );
    312 }
    313 
    314 /*-----------------------------------------------------------------------------
    315 Routine Name: scan_get_by_bssid
    316 Routine Description: Gets scan_result pointer to item by bssid
    317 Arguments:
    318    mydrv   - pointer to private driver data structure
    319    bssid   - pointer to bssid value
    320 Return Value: pointer to scan_result item
    321 -----------------------------------------------------------------------------*/
    322 scan_result_t *scan_get_by_bssid( struct wpa_driver_ti_data *mydrv, u8 *bssid )
    323 {
    324     SHLIST *head = &(mydrv->scan_merge_list);
    325     SHLIST *item;
    326     scan_result_t *cur_res;
    327     scan_ssid_t *p_ssid;
    328 
    329     item = shListGetFirstItem(head);
    330     if( item == NULL )
    331         return( NULL );
    332     do {
    333         cur_res = (scan_result_t *)&(((scan_merge_t *)(item->data))->scanres);
    334         p_ssid = scan_get_ssid(cur_res);
    335         if( (!os_memcmp(cur_res->bssid, bssid, ETH_ALEN)) &&
    336             (!IS_HIDDEN_AP(p_ssid)) ) {
    337             return( cur_res );
    338         }
    339         item = shListGetNextItem(head, item);
    340     } while( item != NULL );
    341 
    342     return( NULL );
    343 }
    344