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
scan_get_ssid(scan_result_t * res_ptr)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 -----------------------------------------------------------------------------*/
scan_init(struct wpa_driver_ti_data * mydrv)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 -----------------------------------------------------------------------------*/
scan_free(void * ptr)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 -----------------------------------------------------------------------------*/
scan_exit(struct wpa_driver_ti_data * mydrv)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 -----------------------------------------------------------------------------*/
scan_count(struct wpa_driver_ti_data * mydrv)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 -----------------------------------------------------------------------------*/
scan_equal(void * val,void * idata)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 -----------------------------------------------------------------------------*/
copy_scan_res(scan_result_t * dst,scan_result_t * src)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 -----------------------------------------------------------------------------*/
scan_add(SHLIST * head,scan_result_t * res_ptr)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 -----------------------------------------------------------------------------*/
scan_find(scan_merge_t * scan_ptr,scan_result_t * results,unsigned int number_items)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 -----------------------------------------------------------------------------*/
scan_dup(scan_result_t * res_ptr)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
scan_merge(struct wpa_driver_ti_data * mydrv,scan_result_t ** results,int force_flag,unsigned int number_items,unsigned int max_size)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 -----------------------------------------------------------------------------*/
scan_get_by_bssid(struct wpa_driver_ti_data * mydrv,u8 * bssid)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