diff -r 000000000000 -r af10295192d8 tcpiputils/dhcp/src/DHCPIP6IA.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tcpiputils/dhcp/src/DHCPIP6IA.cpp Tue Jan 26 15:23:49 2010 +0200 @@ -0,0 +1,368 @@ +// Copyright (c) 2004-2009 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: +// Implements the DHCPIP6 Identity Association classes +// +// + +/** + @file DHCPIP6IA.cpp + @internalTechnology +*/ + +#include "DHCPIP6IA.h" +#include "DHCP_Std.h" +#include "DHCPServer.h" +#include + +#ifdef _DEBUG +#include +#endif + +using namespace DHCPv6; + +COptionNode* CDHCPOptionIA_TA::NewL() + { + return new(ELeave)CDHCPOptionIA_TA(); + } + +COptionNode* CDHCPOptionIA_NA::NewL() + { + return new(ELeave)CDHCPOptionIA_NA(); + } + +CDHCPOptionIAAddress::~CDHCPOptionIAAddress() + { + iNext = NULL; //prevent the base from deleting its members + } + +TInt CDHCPOptionIAAddress::GetAddressOptionL( TPtr8& aPtr, SIPAddressInfo& aAddressInfo ) + { + if ( aPtr.Length() <= KOptionHeaderLength || + TBigEndian::GetValue( aPtr.Ptr() + KOptionCodeOffset, KOptionCodeLen ) != EIaAddr ) + { + return KErrNotFound; + } + ParseL( aPtr ); + aPtr.Set( GetBodyDes() ); + iRecord.ParseL( aPtr ); + + // Must ensure IP6 address is word aligned! So declare it locally + TIp6Addr ip6addr; + Mem::Copy(&ip6addr,iAddress.GetBodyPtr(),KIp6AddressLength); + + aAddressInfo.iAddress.SetAddress( ip6addr ); + aAddressInfo.iPreferredLifeTime = iPreferredLifeTime.GetBigEndian(); + aAddressInfo.iValidLifeTime = iValidLifeTime.GetBigEndian(); + CDHCPOptionStatusCode* pStatus = static_cast(GetOptions().FindOption( EStatusCode )); + aAddressInfo.iStatusCode = pStatus ? pStatus->GetStatusCode() : ESuccess; + + return KErrNone; + } + + +TInt CDHCPOptionIAAddress::AddAddressOptionL( TPtr8& aPtr, SIPAddressInfo& aAddressInfo, TStatusCodes aStatusCodeToSend ) + { + InitialiseL(aPtr); + CDHCPOptionStatusCode* option = NULL; + if(aStatusCodeToSend != EStatusUnknown) + { + option = static_cast(iOptions.AddNodeL(EStatusCode, KDHCPOptionStatusCodeLength)); + } + iRecord.InitialiseL(aPtr); + Header().SetInitialValue(KDHCPOptionIAAddressWithStatusCodeLength - KOptionHeaderLength); + SetLength(); + + SetOpCode(static_cast(EIaAddr)); + TIp6Addr* ip6addr = reinterpret_cast(iAddress.GetBodyPtr() ); + + //-- carefully copy one object to another. See function description + ObjectByteCopy(ip6addr, &aAddressInfo.iAddress.Ip6Address()); + + iPreferredLifeTime.SetBigEndian( aAddressInfo.iPreferredLifeTime ); + iValidLifeTime.SetBigEndian( aAddressInfo.iValidLifeTime ); + if(option) + { + option->SetOpCode(static_cast(EStatusCode)); + option->SetStatusCode(aStatusCodeToSend); + } + + return KErrNone; + } + +TPtr8 CDHCPOptionIA_TA::GetOptionsDes() const + { + TPtr8 ptr(GetBodyDes()); + TInt len = ptr.Length() - KDHCPOptionIA_NATInitLength; + return TPtr8( const_cast(ptr.Ptr()) + KDHCPOptionIA_IAIDLength, len, len ); + } + +TPtr8 CDHCPOptionIA_NA::GetOptionsDes() const + { + TPtr8 ptr(GetBodyDes()); + TInt len = ptr.Length() - KDHCPOptionIA_NATInitLength; + return TPtr8( const_cast(ptr.Ptr()) + KDHCPOptionIA_NATInitLength, len, len ); + } + +START_ATTRIBUTE_TABLE( SIdentityAssociationConfigInfo, KDHCPv6Persinstence, 0 ) + REGISTER_ATTRIBUTE( SIdentityAssociationConfigInfo, iIAID, TMetaNumber ) + REGISTER_ATTRIBUTE( SIdentityAssociationConfigInfo, iAddressInfo, TMetaArray ) +END_ATTRIBUTE_TABLE() + +void SIdentityAssociationConfigInfo::Reset() + { + TDhcpRnd rnd; + iIAID = rnd.Rnd( KDHCPv6IA_NANumberSpaceMin, KDHCPv6IA_NANumberSpaceMax ); + iAddressInfo.Reset(); + } + +void SIdentityAssociationConfigInfo::SetAddressStatus( TInt aIndex, TStatusCodes aStatusCode ) + { + if ( aIndex == KAddrIndexAll ) + { + TInt count = iAddressInfo.Count(); + for(TInt addrInfoIdx=0;addrInfoIdxAddAddressOptionL( ptr, addressInfo, statusCodeToSend ); + if ( remove ) + { + iAddressInfo.Remove( --addrInfoIdx ); + } + } + //write the IA option len into the msg buffer + aDHCPOptionIA.Header().SetInitialValue( ptr.Length() ); + aDHCPOptionIA.SetLength(); + CleanupStack::PopAndDestroy(); + return ptr.Length() - len; //return te length of what we've just put in (address options) + } + +void SIdentityAssociationConfigInfo::ExtractAddressesL( CDHCPOptionIA& aDHCPOptionIA, TUint32 aRebindTimeSpan ) + { + CDHCPOptionIAAddress* optionIaAddress = CDHCPOptionIAAddress::NewL(); + CleanupStack::PushL( optionIaAddress ); + + TPtr8 ptr( aDHCPOptionIA.GetOptionsDes() ); + SIPAddressInfo addressInfoNew; + + while (optionIaAddress->GetAddressOptionL( ptr, addressInfoNew ) == KErrNone) + { + iAddressInfo.AppendL( addressInfoNew ); + } + CleanupStack::PopAndDestroy(); + + //check validity and remove what's not needed + for(TInt addrInfoIdx=0;addrInfoIdx addressInfo.iValidLifeTime || + aRebindTimeSpan > addressInfo.iValidLifeTime || + addressInfo.iStatusCode != ESuccess ) + { + addressInfo.iStatusCode = EMarkForDecline; + } + } + } + +START_ATTRIBUTE_TABLE( SIdentityAssociationConfigInfoNA, KDHCPv6Persinstence, 0 ) + REGISTER_ATTRIBUTE( SIdentityAssociationConfigInfoNA, iT1, TMetaNumber ) + REGISTER_ATTRIBUTE( SIdentityAssociationConfigInfoNA, iT2, TMetaNumber ) +END_ATTRIBUTE_TABLE_BASE(SIdentityAssociationConfigInfo,KDHCPv6PersinstenceId.iUid) + +void SIdentityAssociationConfigInfoNA::ExtractIAOptionInfoL( CDHCPOptionIA_NA& aDHCPOptionIA ) + { + iT1 = aDHCPOptionIA.GetT1(); + iT2 = aDHCPOptionIA.GetT2(); + ExtractAddressesL( aDHCPOptionIA, iT2 ); + } + +void TInterfaceConfigInfo::AppendIAOptionsL(CDHCPMessageHeaderIP6& aMessage, TMessageType aMessageType) + { + CDHCPOptionIA_NA* pIA_NA = static_cast(aMessage.AddOptionL(EIaNa, KDHCPOptionIA_NATInitLength)); + pIA_NA->SetIAID(iSIdentityAssociationConfigInfoNA.IaId()); + // indicate no preference for T1 and T2 + pIA_NA->SetT1(KIA_NoTimePreference); + pIA_NA->SetT2(KIA_NoTimePreference); + switch(aMessageType) + { + case ESolicit: + break; + case EConfirm: + case ERenew: + case ERebind: + pIA_NA->SetT1(iSIdentityAssociationConfigInfoNA.iT1); + pIA_NA->SetT2(iSIdentityAssociationConfigInfoNA.iT2); + //fall through + case ERequest: + case ERelease: + case EDecline: + { + TInt addrOptLen = iSIdentityAssociationConfigInfoNA.AddAddressesL(*pIA_NA,aMessageType); + TPtr8 msg = aMessage.Message().Des(); + msg.SetLength( msg.Length() + addrOptLen); + break; + } + default: + User::Leave(KErrNotSupported); + } + + } + +void TInterfaceConfigInfo::ParseIAOptionsL(CDHCPMessageHeaderIP6& aMessage) + { + // Find an NA option + CDHCPOptionIA_NA* optionIa = static_cast(aMessage.GetOptions().FindOption(EIaNa)); + if (!optionIa || optionIa->GetT1() > optionIa->GetT2()) + {//nothing to do the fact that we don't have any address is picked up when the address is being + //congfigured + return; + } + if ( aMessage.GetMessageType() == EReply ) + { + iSIdentityAssociationConfigInfoNA.ResetAddressInfos(); + iSIdentityAssociationConfigInfoNA.ExtractIAOptionInfoL( *optionIa ); + } + } + +void TInterfaceConfigInfo::CheckForUnicast( CDHCPMessageHeaderIP6& aMessage ) + { + COptionNode* pNode = aMessage.GetOptions().FindOption(EUnicast); + if ( pNode ) + { + iUseUnicast = ETrue; + + // Must ensure IP6 address is word aligned! So declare it locally + TIp6Addr ip6addr; + Mem::Copy(&ip6addr,pNode->GetBodyPtr(),KIp6AddressLength); + + iServerAddress.SetAddress( ip6addr ); + } + } + +void TInterfaceConfigInfo::GetServerAddress( TInetAddr& aAddress ) // to send/receive data + { + __CFLOG_VAR((KLogSubSysDHCP, KLogCode, _L8("TInterfaceConfigInfo::GetServerAddress unicast %d"), iUseUnicast)); + if ( iUseUnicast ) + { + aAddress = iServerAddress; + } + else + { + aAddress.SetAddress( KDHCPv6RelayAgentsNServers ); + } +#ifdef _DEBUG + // Simulate initialisation, renewal or rebind failure by using the wrong port. + if( ( CDHCPServer::DebugFlags() & KDHCP_FailDiscover ) || ( CDHCPServer::DebugFlags() & KDHCP_FailRenew ) || ( CDHCPServer::DebugFlags() & KDHCP_FailRebind ) ) + { + aAddress.SetPort(KDhcpv6WrongDestPort); + } + else + { + TInt destPort; + RProperty::Get(KMyPropertyCat, KMyPropertyDestPortv6, destPort); + aAddress.SetPort(destPort); + } +#else + aAddress.SetPort(KDhcpv6DestPort); +#endif + } + +/** + * Creates one IAID for TA(SIdentityAssociationConfigInfoTA) and + * one for NA(SIdentityAssociationConfigInfoNA) in case they don't exist yet + * (restored after reboot, sleep,....) + * + * @see SIdentityAssociationConfigInfoTA, SIdentityAssociationConfigInfoNA + * @internalTechnology + */ +void DHCPv6::TInterfaceConfigInfo::Reset() + { + ResetUseUnicast(); + //iSIdentityAssociationConfigInfoTA.iIAID = rnd.Rnd( KDHCPv6IA_TANumberSpaceMin, KDHCPv6IA_TANumberSpaceMax ); + iSIdentityAssociationConfigInfoNA.Reset(); + + // Clear the DHCP server address now that we no longer have a lease. + iServerAddress.SetAddress( KInet6AddrNone ); + }