upnp/upnpstack/upnputils/src/upnpipaddressutils.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:12:20 +0200
changeset 0 f5a58ecadc66
permissions -rw-r--r--
Revision: 201003

/** @file
* Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "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:  IP Address utils
*
*/


// INCLUDES
#include <e32base.h>
#include <commdb.h>
#include <in_sock.h>
#include "upnpipaddressutils.h"
#define KLogFile _L("DLNAWebServer.txt")
#include "upnpcustomlog.h"

// ================= MEMBER FUNCTIONS =======================
namespace UpnpIpAddressUtil
    {
// -----------------------------------------------------------------------------
// UpnpIpAddressUtil::GetIfNameForIap
// Reads the IF name for the specified IAP ID.
// -----------------------------------------------------------------------------
//
    EXPORT_C void GetIfNameForIap( TUint32 aIapId, TDes& aIfName )
        {
        CCommsDatabase* theDb;
        TUint32 iapId;
        TBool nameNotFound = ETrue;

        // First zero the name. If IF Name is not found, it will be zero lenght.
        aIfName.Zero();

        // Open CommDB
        theDb = CCommsDatabase::NewL( EDatabaseTypeIAP );
        CleanupStack::PushL( theDb );

        theDb->ShowHiddenRecords();

        // Open IAP table and find the IAP ID given as method parameter.
        CCommsDbTableView* view = theDb->OpenTableLC( TPtrC( IAP ) );
        TInt res = view->GotoFirstRecord();
        while ( res == KErrNone && nameNotFound )
            {
            // Read IAP ID and match it to the one given as parameter
            view->ReadUintL( TPtrC( COMMDB_ID ), iapId );
            if ( iapId == aIapId )
                {
                // Right IAP found, read bearer ID and type
                TUint32 iapBearerId;
                view->ReadUintL( TPtrC( IAP_BEARER ),iapBearerId );
                view->ReadTextL( TPtrC( IAP_BEARER_TYPE ),aIfName );

                // Find the correct bearer table specified by bearer type
                CCommsDbTableView* ifView = theDb->OpenTableLC( 
                    TPtrC( aIfName ) );
                TInt bearerRes = ifView->GotoFirstRecord();
                TUint32 bearerId;
                while ( bearerRes == KErrNone && nameNotFound )
                    {
                    ifView->ReadUintL( TPtrC( COMMDB_ID ), bearerId );
                    // Find out right bearer record and read IF name
                    if ( bearerId == iapBearerId )
                        {
                        // Read the IF name, it is returned in the method
                        // parameter
                        ifView->ReadTextL( TPtrC( IF_NAME ),aIfName );
                        nameNotFound = EFalse;
                        }
                    // Bearer id does not match, check next record
                    else
                        {
                        bearerRes = ifView->GotoNextRecord();
                        }
                    }
                CleanupStack::PopAndDestroy( ifView );
                }
            // IAP id does not match, check next record
            else
                {
                res = view->GotoNextRecord();
                }
            }
        CleanupStack::PopAndDestroy( view );
        CleanupStack::PopAndDestroy( theDb );
        }

// -----------------------------------------------------------------------------
// UpnpFileUtil::MatchIfNameWithIpInterface
// Matches IF name with IP address of the TCP/IP stack interfaces.
// -----------------------------------------------------------------------------
//
    EXPORT_C TInetAddr MatchIfNameWithIpInterface( RSocketServ& aSocketServer,
                                                   TDesC& aIfName,
                                                   TInt& aInterfaceIndex )
        {
        // Buffer for IP address
        const TUint KAddrOutputLength = 50;
        TBuf<KAddrOutputLength> address;
        TPckgBuf<TSoInetInterfaceInfo> info;
        TInetAddr localIpAddress;        
        TInetAddr autoIpAddress;
        TInt autoIfIndex = 0;
        RSocket sock;
        TBool autoIpFound = EFalse;
        TBool ipFound = EFalse;

        _LIT( KUdpProtocol, "udp" );
        _LIT( KLoop4Interface, "loop4" );
        _LIT( KLoop6Interface, "loop6" );
        _LIT( KNoAddress, "0.0.0.0");
        _LIT( KLocalHost, "127.0.0.1");
        _LIT( KWlanIPv6IfSearchString, "wlan6[*");
        _LIT( KWlanIPv4IfSearchString, "wlan[*");
        _LIT( KWlanIfMatchString, "wlan*");
        _LIT( KEtherIfSearchString, "eth[*");
        _LIT( KEtherIfMatchString, "eth*");
        // BT PAN is the same for both info and NIF name
        _LIT( KBtPanIfSearchString, "btpannif*");
        _LIT( KAutoIpMatch, "169.254.*");
        
        //the default interface index
        aInterfaceIndex = 0;
        
        TInt ret= sock.Open( aSocketServer, KUdpProtocol );
        if ( KErrNone == ret )
            {
            ret = sock.SetOpt( KSoInetEnumInterfaces, KSolInetIfCtrl );
            }

        if ( KErrNone == ret )
            {
            while( KErrNone == sock.GetOpt( 
                       KSoInetNextInterface, KSolInetIfCtrl, info ) )
                {

                // If state is up and name is not empty, loop4 or loop6, 
                // then get the address
                if ( ( EIfUp == info().iState ) &&
                     ( 0 != info().iName.Length() ) &&
                     ( 0 != info().iName.Match( KLoop4Interface ) ) && 
                     ( 0 != info().iName.Match( KLoop6Interface ) ) )
                    {
                    // Check if we have valid IP
                    address.Zero();
                    info().iAddress.Output( address );

                    if ( ( 0 < address.Length() ) && 
                         ( 0 != address.Match( KNoAddress ) ) &&
                         ( 0 != address.Match( KLocalHost ) ) )
                        {
                        
                        // read index of interface 
                                        
                        TPckgBuf<TSoInetIfQuery> query;
    					query().iName = info().iName;
    					
    					TInt index;
    					ret=sock.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, query);
    					if(KErrNone==ret)
    					    {
    					    index = query().iIndex;
                   
                            // For ethernet, WLAN and BT PAN interfaces, 
                            // change the match string to suit right interfaces
                            if ( 0 <= info().iName.MatchC( KEtherIfSearchString ) )
                                {
                                // Set the IF name for ETH Match operation below.
                                info().iName.Copy( KEtherIfMatchString );
                                }
                            else if ( 0 <= info().iName.MatchC( 
                                KWlanIPv4IfSearchString ) )
                                {
                                // Set the IF name for WLAN Match operation below.
                                info().iName.Copy( KWlanIfMatchString );
                                }
                            else if ( 0 <= info().iName.MatchC( 
                                    KBtPanIfSearchString ) )
                                {
                                // Set the IF name for BT PAN Match operation below.
                                info().iName.Copy( KBtPanIfSearchString );
                                }

                            // Exlude IPv6 addresses, they are not supported.
                            // If IF name matches with the one given as parameter,
                            // then we have the same interface with IP.
                            if ( ( 0 > info().iName.MatchC( KWlanIPv6IfSearchString ) ) &&
                                 ( 0 <= aIfName.MatchC( info().iName ) ) )
                                {
                                // If the address is auto-ip, check whether there 
                                // is also DHCP IP in the same interface.
                                if ( 0 <= address.Match( KAutoIpMatch ) )
                                    {
                                    autoIpFound = ETrue;
                                    autoIpAddress = info().iAddress;
                                    autoIpAddress.ConvertToV4();
                                    autoIfIndex = index;
                                    }
                                // Other than auto IP
                                else
                                    {
                                    ipFound = ETrue;
                                    localIpAddress = info().iAddress;
                                    // we're using ipv4 addresses
                                    localIpAddress.ConvertToV4();
                                    aInterfaceIndex = index;
                                    }
                                }
    					    }
                        }
                    }
                }
            }
        sock.Close();

        // If only auto-IP was found, then return it.
        // If only DHCP IP was found or also auto-IP, then return the
        // DHCP IP which is already placed in localIpAddress variable.
        // It is not possible that there is no IP as the connection has
        // been started already by the UPnP application and this method can't
        // be called if there is no connection.
        if ( !ipFound && autoIpFound )
            {
            localIpAddress = autoIpAddress;
            aInterfaceIndex = autoIfIndex;
            }

        address.Zero();
        localIpAddress.Output( address );

        // return the address
        return localIpAddress;
        }
    }

//  End of File