wlan_bearer/wlanengine/wlan_common/wlanengine_common_3.1/src/genscaninfo.cpp
changeset 0 c40eb8fe8501
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wlan_bearer/wlanengine/wlan_common/wlanengine_common_3.1/src/genscaninfo.cpp	Tue Feb 02 02:03:13 2010 +0200
@@ -0,0 +1,405 @@
+/*
+* Copyright (c) 2002-2005 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Class to dig information of scan results.
+*
+*/
+
+
+#include "genscaninfo.h"
+#include "genscaninfoie.h"
+
+// Default values for information element IDs.
+const u8_t WPA_IE_ID              = 221;
+const u8_t SCAN_WPA_OUI_LENGTH    = 4;
+const u8_t SCAN_WPA_OUI[]         = { 0x00, 0x50, 0xF2, 0x01 };
+const u8_t SCAN_WSC_OUI[]         = { 0x00, 0x50, 0xF2, 0x04 };
+
+const u8_t SCAN_OUI_TYPE_OFFSET = 3;
+const u8_t SCAN_OUI_SUBTYPE_OFFSET = 4;
+
+/** Offset from AttributeType field to DataLength field */
+const u8_t SCAN_WSC_IE_DATA_LENGTH_OFFSET = 2;
+
+/** Offset from AttributeType field to Data field */
+const u8_t SCAN_WSC_IE_DATA_AREA_OFFSET = 4;
+
+/** Offset to first Protected Setup attribute type in IE */
+const u8_t SCAN_WSC_IE_PROTECTED_SETUP_DATA_OFFSET = 2+4;
+
+/** IDs for different data elements in WSC IE. */
+const u16_t SCAN_WSC_IE_AP_SETUP_LOCKED       = 0x1057;
+
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+ScanInfo::ScanInfo( const ScanList& scan_list ) :
+    ScanListIterator( scan_list ), 
+    ie_iter_m( current_m + MGMT_BODY_OFFSET )
+    {
+    }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+WlanSecurityMode ScanInfo::SecurityMode()
+    {
+    ScanInfoIe ie;
+    return ie.SecurityMode( *this );
+    }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+WlanScanError ScanInfo::InformationElement(
+    u8_t ie_id, 
+    u8_t& ie_length, 
+    const u8_t** ie_data )
+    {
+    // IE is not found when the whole scan info element is gone through.
+    //
+    // The Element format is:
+    // +----+----+--...--+
+    // | a  | b  | c     |
+    // +----+----+--...--+
+    // where
+    // a) Element ID (1 byte)
+    // b) Length (1 byte)
+    // c) Information (length bytes)
+    //
+
+    u8_t ie, len;
+    const u8_t* data;
+
+    if ( FirstIE( ie, len, &data ) != WlanScanError_Ok )
+        {
+        ie_length = 0;
+        *ie_data = NULL;
+        return WlanScanError_IeNotFound;
+        }
+
+    WlanScanError ret( WlanScanError_Ok );
+
+    while ( ie != ie_id && ret == WlanScanError_Ok )
+        {
+        ret = NextIE( ie, len, &data );
+        }
+
+    ie_length = len;
+    *ie_data = data;
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+WlanScanError ScanInfo::WpaIE(
+    u8_t& ie_length, 
+    const u8_t** ie_data )
+    {
+    // Element format is:
+    // +----+-----+-----+-----+------+-------+--...--+-------+--...--+--------+
+    // | ID | Len | OUI | Ver | GKCS | PKCSC | PKSCL | AKMSC | AKMSL | RSNCap |
+    // +----+-----+-----+-----+------+-------+--...--+-------+--...--+--------+
+    // where
+    // ID     = Element ID = 221 (1 octet)
+    // Len    = Length (1 octet)
+    // OUI    = 00:50:F2:01 (4 octets)
+    // Ver    = Version (2 octets)
+    // GKCS   = Group Key Cipher Suite (4 octets)
+    // PKCSC  = Pairwise Key Cipher Suite Count (2 octets)
+    // PKCSL  = Pairwise Key Cipher Suite List (4*m octets)
+    // AKMSC  = Authenticated Key Management Suite Count (2 octets)
+    // AKMSL  = Authenticated Key Management Suite List (4*n octets)
+    // RSNCap = RSN Capabilities
+
+    u8_t ie( WPA_IE_ID ), len;
+    const u8_t* data;
+
+    // Find out the first element
+    if ( InformationElement( WPA_IE_ID, len, &data ) != WlanScanError_Ok )
+        { // Okay, it didn't exist.
+        ie_length = 0;
+        *ie_data = NULL;
+        return WlanScanError_IeNotFound;
+        }
+
+    // The ID is correct but check also the UID.
+    WlanScanError ret( WlanScanError_Ok );
+
+    while ( ret == WlanScanError_Ok &&
+            ( ie != WPA_IE_ID ||
+              len < SCAN_WPA_OUI_LENGTH ||
+              !( data[0] == SCAN_WPA_OUI[0] && data[1] == SCAN_WPA_OUI[1] &&
+                 data[2] == SCAN_WPA_OUI[2] && data[3] == SCAN_WPA_OUI[3] ) ) )
+        {
+        ret = NextIE( ie, len, &data );
+        }
+
+    // Check is the element was corrupted
+    if ( ie != WPA_IE_ID )
+        {
+        ie_length = 0;
+        *ie_data = NULL;
+        return WlanScanError_IeNotFound;
+        }
+
+    ie_length = len;
+    *ie_data = data;
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+WlanScanError ScanInfo::InformationElement(
+    u8_t ie_id,
+    const WlanIeOui& ie_oui,
+    u8_t ie_oui_type,
+    u8_t& ie_length, 
+    const u8_t** ie_data )
+    {
+    // Element format is:
+    // +----+-----+-----+-----+------+-------+--...--+-------+--...--+--------+
+    // | ID | Len | OUI |     |      |       |       |       |       |        |
+    // +----+-----+-----+-----+------+-------+--...--+-------+--...--+--------+
+    // where
+    // ID     = Element ID (1 octet)
+    // Len    = Length (1 octet)
+    // OUI    = OUI (3 octets)
+    // OUItyp = OUI Type (1 octet)
+
+    u8_t ie( ie_id ); 
+    u8_t len( 0 );
+    const u8_t* data;
+
+    // Find the first element
+    if ( InformationElement( ie_id, len, &data ) 
+         != WlanScanError_Ok )
+        { // Okay, it didn't exist.
+        ie_length = 0;
+        *ie_data = NULL;
+        return WlanScanError_IeNotFound;
+        }
+
+    // The ID is correct but also the OUI and OUI Type need to match
+    WlanScanError ret( WlanScanError_Ok );
+
+    while ( ret == WlanScanError_Ok && 
+            ( ie != ie_id || 
+              !( data[0] == ie_oui[0] && 
+                 data[1] == ie_oui[1] &&
+                 data[2] == ie_oui[2] 
+               ) ||
+              *( data + SCAN_OUI_TYPE_OFFSET ) != ie_oui_type
+            ) 
+          )
+        {
+        ret = NextIE( ie, len, &data );
+        }
+
+    // Check if the element is corrupted
+    if ( ie != ie_id )
+        {
+        ie_length = 0;
+        *ie_data = NULL;
+        return WlanScanError_IeNotFound;
+        }
+
+    ie_length = len;
+    *ie_data = data;
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+WlanScanError ScanInfo::InformationElement(
+    u8_t ie_id,
+    const WlanIeOui& ie_oui,
+    u8_t ie_oui_type,
+    u8_t ie_oui_subtype,
+    u8_t& ie_length, 
+    const u8_t** ie_data )
+    {
+    // Element format is:
+    // +----+-----+-----+-----+------+-------+--...--+-------+--...--+--------+
+    // | ID | Len | OUI |     |      |       |       |       |       |        |
+    // +----+-----+-----+-----+------+-------+--...--+-------+--...--+--------+
+    // where
+    // ID     = Element ID (1 octet)
+    // Len    = Length (1 octet)
+    // OUI    = OUI (3 octets)
+    // OUItyp = OUI Type (1 octet)
+
+    u8_t ie( ie_id ); 
+    u8_t len( 0 );
+    const u8_t* data;
+
+    // Find the first element
+    if ( InformationElement( ie_id, len, &data ) 
+         != WlanScanError_Ok )
+        { // Okay, it didn't exist.
+        ie_length = 0;
+        *ie_data = NULL;
+        return WlanScanError_IeNotFound;
+        }
+
+    // The ID is correct but also the OUI and OUI Type need to match
+    WlanScanError ret( WlanScanError_Ok );
+
+    while ( ret == WlanScanError_Ok && 
+            ( ie != ie_id || 
+              !( data[0] == ie_oui[0] && 
+                 data[1] == ie_oui[1] &&
+                 data[2] == ie_oui[2] 
+               ) ||
+              *( data + SCAN_OUI_TYPE_OFFSET ) != ie_oui_type ||
+              *( data + SCAN_OUI_SUBTYPE_OFFSET ) != ie_oui_subtype              
+            ) 
+          )
+        {
+        ret = NextIE( ie, len, &data );
+        }
+
+    // Check if the element is corrupted
+    if ( ie != ie_id )
+        {
+        ie_length = 0;
+        *ie_data = NULL;
+        return WlanScanError_IeNotFound;
+        }
+
+    ie_length = len;
+    *ie_data = data;
+    return ret;
+    }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+WlanScanError ScanInfo::FirstIE( 
+    u8_t& ie_id, 
+    u8_t& ie_length, 
+    const u8_t** ie_data )
+    {
+    if( !current_m )
+        {
+        return WlanScanError_IeNotFound;
+        }
+    ie_iter_m = current_m + MGMT_BODY_OFFSET;
+    return CurrentIE( ie_id, ie_length, ie_data );
+    }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+WlanScanError ScanInfo::NextIE(
+    u8_t& ie_id, 
+    u8_t& ie_length, 
+    const u8_t** ie_data )
+    {
+    if( !current_m )
+        {
+        return WlanScanError_IeNotFound;
+        }
+    ie_iter_m += *( ie_iter_m + 1 ) + 2;
+    return CurrentIE( ie_id, ie_length, ie_data );
+    }
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+WlanScanError ScanInfo::CurrentIE(
+    u8_t& ie_id, 
+    u8_t& ie_length, 
+    const u8_t** ie_data ) const
+    {
+    if ( !current_m || ie_iter_m >= current_m + Size() )
+        {
+        ie_id = 0;
+        ie_length = 0;
+        *ie_data = NULL;
+        return WlanScanError_IeNotFound;
+        }
+
+    ie_id = *ie_iter_m;
+    ie_length = *( ie_iter_m+1 );
+    *ie_data = ie_iter_m+2;
+    return WlanScanError_Ok;
+}
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+//
+bool_t ScanInfo::IsProtectedSetupSupported()
+    {
+    u8_t ie_length = 0;
+    const u8_t* ie_data = NULL;
+    const WlanIeOui ie_oui = { SCAN_WSC_OUI[0], SCAN_WSC_OUI[1], SCAN_WSC_OUI[2] };
+    const u8_t ie_oui_type = SCAN_WSC_OUI[3];
+    
+    WlanScanError err = InformationElement( WPA_IE_ID,
+                                            ie_oui, ie_oui_type,
+                                            ie_length, &ie_data );
+    
+    if (err == WlanScanError_IeNotFound
+        || ie_data == NULL 
+        || ie_length == 0 )
+        {
+        return false_t;
+        }
+    
+    // WSC IE is found, next check whether AP setup is locked (locked state would prevent use of Protected Setup)
+    return !IsApSetupLocked( ie_data, ie_length );
+    }
+
+
+// ---------------------------------------------------------------------------
+// ---------------------------------------------------------------------------
+bool_t ScanInfo::IsApSetupLocked(
+    const u8_t* ie_data,
+    const u8_t ie_length ) const
+    {
+    u16_t index( SCAN_WSC_IE_PROTECTED_SETUP_DATA_OFFSET );
+    
+    while ( (index + SCAN_WSC_IE_DATA_LENGTH_OFFSET + 1) < ie_length)
+        {
+        // Make big endian to little endian conversion.
+        u16_t attribute_type = (ie_data[index]<<8) 
+                             | (ie_data[index+1]);
+        
+        u16_t attribute_data_length = (ie_data[index + SCAN_WSC_IE_DATA_LENGTH_OFFSET]<<8) 
+                                    | (ie_data[index + SCAN_WSC_IE_DATA_LENGTH_OFFSET+1]);
+        
+        // Check if all attribute data does not fit current IE.
+        if ( ( index + attribute_data_length + SCAN_WSC_IE_DATA_AREA_OFFSET ) > ie_length)
+            {
+            // attribute does not fit current IE
+            return false_t;
+            }
+            
+        if (attribute_type == SCAN_WSC_IE_AP_SETUP_LOCKED)
+            {
+            // AP setup locked attribute found, return its value.
+            return ie_data[index + SCAN_WSC_IE_DATA_AREA_OFFSET];
+            }
+        
+        // update index to start of next attribute
+        index += SCAN_WSC_IE_DATA_AREA_OFFSET + attribute_data_length;
+        }
+    // 
+    return false_t;
+    }