• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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