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