|
1 /* |
|
2 * Copyright (c) 2002-2005 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of the License "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Class to dig information of scan results. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include "genscaninfo.h" |
|
20 #include "genscaninfoie.h" |
|
21 |
|
22 // Default values for information element IDs. |
|
23 const u8_t WPA_IE_ID = 221; |
|
24 const u8_t SCAN_WPA_OUI_LENGTH = 4; |
|
25 const u8_t SCAN_WPA_OUI[] = { 0x00, 0x50, 0xF2, 0x01 }; |
|
26 const u8_t SCAN_WSC_OUI[] = { 0x00, 0x50, 0xF2, 0x04 }; |
|
27 |
|
28 const u8_t SCAN_OUI_TYPE_OFFSET = 3; |
|
29 const u8_t SCAN_OUI_SUBTYPE_OFFSET = 4; |
|
30 |
|
31 /** Offset from AttributeType field to DataLength field */ |
|
32 const u8_t SCAN_WSC_IE_DATA_LENGTH_OFFSET = 2; |
|
33 |
|
34 /** Offset from AttributeType field to Data field */ |
|
35 const u8_t SCAN_WSC_IE_DATA_AREA_OFFSET = 4; |
|
36 |
|
37 /** Offset to first Protected Setup attribute type in IE */ |
|
38 const u8_t SCAN_WSC_IE_PROTECTED_SETUP_DATA_OFFSET = 2+4; |
|
39 |
|
40 /** IDs for different data elements in WSC IE. */ |
|
41 const u16_t SCAN_WSC_IE_AP_SETUP_LOCKED = 0x1057; |
|
42 |
|
43 // ================= MEMBER FUNCTIONS ======================= |
|
44 |
|
45 // --------------------------------------------------------------------------- |
|
46 // --------------------------------------------------------------------------- |
|
47 // |
|
48 ScanInfo::ScanInfo( const ScanList& scan_list ) : |
|
49 ScanListIterator( scan_list ), |
|
50 ie_iter_m( current_m + MGMT_BODY_OFFSET ) |
|
51 { |
|
52 } |
|
53 |
|
54 // --------------------------------------------------------------------------- |
|
55 // --------------------------------------------------------------------------- |
|
56 // |
|
57 WlanSecurityMode ScanInfo::SecurityMode() |
|
58 { |
|
59 ScanInfoIe ie; |
|
60 return ie.SecurityMode( *this ); |
|
61 } |
|
62 |
|
63 // --------------------------------------------------------------------------- |
|
64 // --------------------------------------------------------------------------- |
|
65 // |
|
66 WlanScanError ScanInfo::InformationElement( |
|
67 u8_t ie_id, |
|
68 u8_t& ie_length, |
|
69 const u8_t** ie_data ) |
|
70 { |
|
71 // IE is not found when the whole scan info element is gone through. |
|
72 // |
|
73 // The Element format is: |
|
74 // +----+----+--...--+ |
|
75 // | a | b | c | |
|
76 // +----+----+--...--+ |
|
77 // where |
|
78 // a) Element ID (1 byte) |
|
79 // b) Length (1 byte) |
|
80 // c) Information (length bytes) |
|
81 // |
|
82 |
|
83 u8_t ie, len; |
|
84 const u8_t* data; |
|
85 |
|
86 if ( FirstIE( ie, len, &data ) != WlanScanError_Ok ) |
|
87 { |
|
88 ie_length = 0; |
|
89 *ie_data = NULL; |
|
90 return WlanScanError_IeNotFound; |
|
91 } |
|
92 |
|
93 WlanScanError ret( WlanScanError_Ok ); |
|
94 |
|
95 while ( ie != ie_id && ret == WlanScanError_Ok ) |
|
96 { |
|
97 ret = NextIE( ie, len, &data ); |
|
98 } |
|
99 |
|
100 ie_length = len; |
|
101 *ie_data = data; |
|
102 return ret; |
|
103 } |
|
104 |
|
105 // --------------------------------------------------------------------------- |
|
106 // --------------------------------------------------------------------------- |
|
107 // |
|
108 WlanScanError ScanInfo::WpaIE( |
|
109 u8_t& ie_length, |
|
110 const u8_t** ie_data ) |
|
111 { |
|
112 // Element format is: |
|
113 // +----+-----+-----+-----+------+-------+--...--+-------+--...--+--------+ |
|
114 // | ID | Len | OUI | Ver | GKCS | PKCSC | PKSCL | AKMSC | AKMSL | RSNCap | |
|
115 // +----+-----+-----+-----+------+-------+--...--+-------+--...--+--------+ |
|
116 // where |
|
117 // ID = Element ID = 221 (1 octet) |
|
118 // Len = Length (1 octet) |
|
119 // OUI = 00:50:F2:01 (4 octets) |
|
120 // Ver = Version (2 octets) |
|
121 // GKCS = Group Key Cipher Suite (4 octets) |
|
122 // PKCSC = Pairwise Key Cipher Suite Count (2 octets) |
|
123 // PKCSL = Pairwise Key Cipher Suite List (4*m octets) |
|
124 // AKMSC = Authenticated Key Management Suite Count (2 octets) |
|
125 // AKMSL = Authenticated Key Management Suite List (4*n octets) |
|
126 // RSNCap = RSN Capabilities |
|
127 |
|
128 u8_t ie( WPA_IE_ID ), len; |
|
129 const u8_t* data; |
|
130 |
|
131 // Find out the first element |
|
132 if ( InformationElement( WPA_IE_ID, len, &data ) != WlanScanError_Ok ) |
|
133 { // Okay, it didn't exist. |
|
134 ie_length = 0; |
|
135 *ie_data = NULL; |
|
136 return WlanScanError_IeNotFound; |
|
137 } |
|
138 |
|
139 // The ID is correct but check also the UID. |
|
140 WlanScanError ret( WlanScanError_Ok ); |
|
141 |
|
142 while ( ret == WlanScanError_Ok && |
|
143 ( ie != WPA_IE_ID || |
|
144 len < SCAN_WPA_OUI_LENGTH || |
|
145 !( data[0] == SCAN_WPA_OUI[0] && data[1] == SCAN_WPA_OUI[1] && |
|
146 data[2] == SCAN_WPA_OUI[2] && data[3] == SCAN_WPA_OUI[3] ) ) ) |
|
147 { |
|
148 ret = NextIE( ie, len, &data ); |
|
149 } |
|
150 |
|
151 // Check is the element was corrupted |
|
152 if ( ie != WPA_IE_ID ) |
|
153 { |
|
154 ie_length = 0; |
|
155 *ie_data = NULL; |
|
156 return WlanScanError_IeNotFound; |
|
157 } |
|
158 |
|
159 ie_length = len; |
|
160 *ie_data = data; |
|
161 return ret; |
|
162 } |
|
163 |
|
164 // --------------------------------------------------------------------------- |
|
165 // --------------------------------------------------------------------------- |
|
166 // |
|
167 WlanScanError ScanInfo::InformationElement( |
|
168 u8_t ie_id, |
|
169 const WlanIeOui& ie_oui, |
|
170 u8_t ie_oui_type, |
|
171 u8_t& ie_length, |
|
172 const u8_t** ie_data ) |
|
173 { |
|
174 // Element format is: |
|
175 // +----+-----+-----+-----+------+-------+--...--+-------+--...--+--------+ |
|
176 // | ID | Len | OUI | | | | | | | | |
|
177 // +----+-----+-----+-----+------+-------+--...--+-------+--...--+--------+ |
|
178 // where |
|
179 // ID = Element ID (1 octet) |
|
180 // Len = Length (1 octet) |
|
181 // OUI = OUI (3 octets) |
|
182 // OUItyp = OUI Type (1 octet) |
|
183 |
|
184 u8_t ie( ie_id ); |
|
185 u8_t len( 0 ); |
|
186 const u8_t* data; |
|
187 |
|
188 // Find the first element |
|
189 if ( InformationElement( ie_id, len, &data ) |
|
190 != WlanScanError_Ok ) |
|
191 { // Okay, it didn't exist. |
|
192 ie_length = 0; |
|
193 *ie_data = NULL; |
|
194 return WlanScanError_IeNotFound; |
|
195 } |
|
196 |
|
197 // The ID is correct but also the OUI and OUI Type need to match |
|
198 WlanScanError ret( WlanScanError_Ok ); |
|
199 |
|
200 while ( ret == WlanScanError_Ok && |
|
201 ( ie != ie_id || |
|
202 !( data[0] == ie_oui[0] && |
|
203 data[1] == ie_oui[1] && |
|
204 data[2] == ie_oui[2] |
|
205 ) || |
|
206 *( data + SCAN_OUI_TYPE_OFFSET ) != ie_oui_type |
|
207 ) |
|
208 ) |
|
209 { |
|
210 ret = NextIE( ie, len, &data ); |
|
211 } |
|
212 |
|
213 // Check if the element is corrupted |
|
214 if ( ie != ie_id ) |
|
215 { |
|
216 ie_length = 0; |
|
217 *ie_data = NULL; |
|
218 return WlanScanError_IeNotFound; |
|
219 } |
|
220 |
|
221 ie_length = len; |
|
222 *ie_data = data; |
|
223 return ret; |
|
224 } |
|
225 |
|
226 // --------------------------------------------------------------------------- |
|
227 // --------------------------------------------------------------------------- |
|
228 // |
|
229 WlanScanError ScanInfo::InformationElement( |
|
230 u8_t ie_id, |
|
231 const WlanIeOui& ie_oui, |
|
232 u8_t ie_oui_type, |
|
233 u8_t ie_oui_subtype, |
|
234 u8_t& ie_length, |
|
235 const u8_t** ie_data ) |
|
236 { |
|
237 // Element format is: |
|
238 // +----+-----+-----+-----+------+-------+--...--+-------+--...--+--------+ |
|
239 // | ID | Len | OUI | | | | | | | | |
|
240 // +----+-----+-----+-----+------+-------+--...--+-------+--...--+--------+ |
|
241 // where |
|
242 // ID = Element ID (1 octet) |
|
243 // Len = Length (1 octet) |
|
244 // OUI = OUI (3 octets) |
|
245 // OUItyp = OUI Type (1 octet) |
|
246 |
|
247 u8_t ie( ie_id ); |
|
248 u8_t len( 0 ); |
|
249 const u8_t* data; |
|
250 |
|
251 // Find the first element |
|
252 if ( InformationElement( ie_id, len, &data ) |
|
253 != WlanScanError_Ok ) |
|
254 { // Okay, it didn't exist. |
|
255 ie_length = 0; |
|
256 *ie_data = NULL; |
|
257 return WlanScanError_IeNotFound; |
|
258 } |
|
259 |
|
260 // The ID is correct but also the OUI and OUI Type need to match |
|
261 WlanScanError ret( WlanScanError_Ok ); |
|
262 |
|
263 while ( ret == WlanScanError_Ok && |
|
264 ( ie != ie_id || |
|
265 !( data[0] == ie_oui[0] && |
|
266 data[1] == ie_oui[1] && |
|
267 data[2] == ie_oui[2] |
|
268 ) || |
|
269 *( data + SCAN_OUI_TYPE_OFFSET ) != ie_oui_type || |
|
270 *( data + SCAN_OUI_SUBTYPE_OFFSET ) != ie_oui_subtype |
|
271 ) |
|
272 ) |
|
273 { |
|
274 ret = NextIE( ie, len, &data ); |
|
275 } |
|
276 |
|
277 // Check if the element is corrupted |
|
278 if ( ie != ie_id ) |
|
279 { |
|
280 ie_length = 0; |
|
281 *ie_data = NULL; |
|
282 return WlanScanError_IeNotFound; |
|
283 } |
|
284 |
|
285 ie_length = len; |
|
286 *ie_data = data; |
|
287 return ret; |
|
288 } |
|
289 |
|
290 // --------------------------------------------------------------------------- |
|
291 // --------------------------------------------------------------------------- |
|
292 // |
|
293 WlanScanError ScanInfo::FirstIE( |
|
294 u8_t& ie_id, |
|
295 u8_t& ie_length, |
|
296 const u8_t** ie_data ) |
|
297 { |
|
298 if( !current_m ) |
|
299 { |
|
300 return WlanScanError_IeNotFound; |
|
301 } |
|
302 ie_iter_m = current_m + MGMT_BODY_OFFSET; |
|
303 return CurrentIE( ie_id, ie_length, ie_data ); |
|
304 } |
|
305 |
|
306 // --------------------------------------------------------------------------- |
|
307 // --------------------------------------------------------------------------- |
|
308 // |
|
309 WlanScanError ScanInfo::NextIE( |
|
310 u8_t& ie_id, |
|
311 u8_t& ie_length, |
|
312 const u8_t** ie_data ) |
|
313 { |
|
314 if( !current_m ) |
|
315 { |
|
316 return WlanScanError_IeNotFound; |
|
317 } |
|
318 ie_iter_m += *( ie_iter_m + 1 ) + 2; |
|
319 return CurrentIE( ie_id, ie_length, ie_data ); |
|
320 } |
|
321 |
|
322 // --------------------------------------------------------------------------- |
|
323 // --------------------------------------------------------------------------- |
|
324 // |
|
325 WlanScanError ScanInfo::CurrentIE( |
|
326 u8_t& ie_id, |
|
327 u8_t& ie_length, |
|
328 const u8_t** ie_data ) const |
|
329 { |
|
330 if ( !current_m || ie_iter_m >= current_m + Size() ) |
|
331 { |
|
332 ie_id = 0; |
|
333 ie_length = 0; |
|
334 *ie_data = NULL; |
|
335 return WlanScanError_IeNotFound; |
|
336 } |
|
337 |
|
338 ie_id = *ie_iter_m; |
|
339 ie_length = *( ie_iter_m+1 ); |
|
340 *ie_data = ie_iter_m+2; |
|
341 return WlanScanError_Ok; |
|
342 } |
|
343 |
|
344 // --------------------------------------------------------------------------- |
|
345 // --------------------------------------------------------------------------- |
|
346 // |
|
347 bool_t ScanInfo::IsProtectedSetupSupported() |
|
348 { |
|
349 u8_t ie_length = 0; |
|
350 const u8_t* ie_data = NULL; |
|
351 const WlanIeOui ie_oui = { SCAN_WSC_OUI[0], SCAN_WSC_OUI[1], SCAN_WSC_OUI[2] }; |
|
352 const u8_t ie_oui_type = SCAN_WSC_OUI[3]; |
|
353 |
|
354 WlanScanError err = InformationElement( WPA_IE_ID, |
|
355 ie_oui, ie_oui_type, |
|
356 ie_length, &ie_data ); |
|
357 |
|
358 if (err == WlanScanError_IeNotFound |
|
359 || ie_data == NULL |
|
360 || ie_length == 0 ) |
|
361 { |
|
362 return false_t; |
|
363 } |
|
364 |
|
365 // WSC IE is found, next check whether AP setup is locked (locked state would prevent use of Protected Setup) |
|
366 return !IsApSetupLocked( ie_data, ie_length ); |
|
367 } |
|
368 |
|
369 |
|
370 // --------------------------------------------------------------------------- |
|
371 // --------------------------------------------------------------------------- |
|
372 bool_t ScanInfo::IsApSetupLocked( |
|
373 const u8_t* ie_data, |
|
374 const u8_t ie_length ) const |
|
375 { |
|
376 u16_t index( SCAN_WSC_IE_PROTECTED_SETUP_DATA_OFFSET ); |
|
377 |
|
378 while ( (index + SCAN_WSC_IE_DATA_LENGTH_OFFSET + 1) < ie_length) |
|
379 { |
|
380 // Make big endian to little endian conversion. |
|
381 u16_t attribute_type = (ie_data[index]<<8) |
|
382 | (ie_data[index+1]); |
|
383 |
|
384 u16_t attribute_data_length = (ie_data[index + SCAN_WSC_IE_DATA_LENGTH_OFFSET]<<8) |
|
385 | (ie_data[index + SCAN_WSC_IE_DATA_LENGTH_OFFSET+1]); |
|
386 |
|
387 // Check if all attribute data does not fit current IE. |
|
388 if ( ( index + attribute_data_length + SCAN_WSC_IE_DATA_AREA_OFFSET ) > ie_length) |
|
389 { |
|
390 // attribute does not fit current IE |
|
391 return false_t; |
|
392 } |
|
393 |
|
394 if (attribute_type == SCAN_WSC_IE_AP_SETUP_LOCKED) |
|
395 { |
|
396 // AP setup locked attribute found, return its value. |
|
397 return ie_data[index + SCAN_WSC_IE_DATA_AREA_OFFSET]; |
|
398 } |
|
399 |
|
400 // update index to start of next attribute |
|
401 index += SCAN_WSC_IE_DATA_AREA_OFFSET + attribute_data_length; |
|
402 } |
|
403 // |
|
404 return false_t; |
|
405 } |