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 23scan_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/*----------------------------------------------------------------------------- 42Routine Name: scan_init 43Routine Description: Inits scan merge list 44Arguments: 45 mydrv - pointer to private driver data structure 46Return Value: 47-----------------------------------------------------------------------------*/ 48void scan_init( struct wpa_driver_ti_data *mydrv ) 49{ 50 mydrv->last_scan = -1; 51 shListInitList(&(mydrv->scan_merge_list)); 52} 53 54/*----------------------------------------------------------------------------- 55Routine Name: scan_free 56Routine Description: Frees scan structure private data 57Arguments: 58 ptr - pointer to private data structure 59Return Value: 60-----------------------------------------------------------------------------*/ 61static void scan_free( void *ptr ) 62{ 63 os_free(ptr); 64} 65 66/*----------------------------------------------------------------------------- 67Routine Name: scan_exit 68Routine Description: Cleans scan merge list 69Arguments: 70 mydrv - pointer to private driver data structure 71Return Value: 72-----------------------------------------------------------------------------*/ 73void scan_exit( struct wpa_driver_ti_data *mydrv ) 74{ 75 shListDelAllItems(&(mydrv->scan_merge_list), scan_free); 76} 77 78/*----------------------------------------------------------------------------- 79Routine Name: scan_count 80Routine Description: Gives number of list elements 81Arguments: 82 mydrv - pointer to private driver data structure 83Return Value: Number of elements in the list 84-----------------------------------------------------------------------------*/ 85unsigned long scan_count( struct wpa_driver_ti_data *mydrv ) 86{ 87 return shListGetCount(&(mydrv->scan_merge_list)); 88} 89 90/*----------------------------------------------------------------------------- 91Routine Name: scan_equal 92Routine Description: Compares bssid of scan result and scan merge structure 93Arguments: 94 val - pointer to scan result structure 95 idata - pointer to scan merge structure 96Return Value: 1 - if equal, 0 - if not 97-----------------------------------------------------------------------------*/ 98static 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/*----------------------------------------------------------------------------- 125Routine Name: copy_scan_res 126Routine Description: copies scan result structure to scan merge list item 127Arguments: 128 dst - pointer to scan result structure in the list 129 src - source pointer to scan result structure 130Return Value: NONE 131-----------------------------------------------------------------------------*/ 132void 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/*----------------------------------------------------------------------------- 144Routine Name: scan_add 145Routine Description: adds scan result structure to scan merge list 146Arguments: 147 head - pointer to scan merge list head 148 res_ptr - pointer to scan result structure 149Return Value: Pointer to scan merge item 150-----------------------------------------------------------------------------*/ 151static 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/*----------------------------------------------------------------------------- 169Routine Name: scan_find 170Routine Description: Looks for scan merge item in scan results array 171Arguments: 172 scan_ptr - pointer to scan merge item 173 results - pointer to scan results array 174 number_items - current number of items 175Return Value: 1 - if item was found, 0 - otherwise 176-----------------------------------------------------------------------------*/ 177static 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/*----------------------------------------------------------------------------- 191Routine Name: scan_dup 192Routine Description: Create copy of scan results entry 193Arguments: 194 res_ptr - pointer to scan result item 195Return Value: pointer to new scan result item, or NULL 196-----------------------------------------------------------------------------*/ 197static 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/*----------------------------------------------------------------------------- 217Routine Name: scan_merge 218Routine Description: Merges current scan results with previous 219Arguments: 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 224Return Value: Merged number of items 225-----------------------------------------------------------------------------*/ 226#ifdef WPA_SUPPLICANT_VER_0_6_X 227unsigned 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 231unsigned 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/*----------------------------------------------------------------------------- 315Routine Name: scan_get_by_bssid 316Routine Description: Gets scan_result pointer to item by bssid 317Arguments: 318 mydrv - pointer to private driver data structure 319 bssid - pointer to bssid value 320Return Value: pointer to scan_result item 321-----------------------------------------------------------------------------*/ 322scan_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