networkingtestandutils/networkingunittest/dummynif/dummynif6.cpp
changeset 0 af10295192d8
child 5 1422c6cd3f0c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/networkingtestandutils/networkingunittest/dummynif/dummynif6.cpp	Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,333 @@
+// Copyright (c) 2003-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:
+//
+
+#include <e32hal.h>	// UserHal::MachineInfo()
+#include <comms-infras/nifif.h>
+#include <nifvar.h>
+#include <nifutl.h>
+#include <es_mbuf.h>
+#include <in_iface.h>
+#include <comms-infras/commsdebugutility.h>
+#include <connectprog.h>
+
+#include <in_chk.h>
+#include <in_sock.h>
+#include <in6_if.h>	// KSoIface*, KIf*, TSoInet6IfConfig
+#include "dummynifvar.h"
+#include "dummynif.h"
+
+
+/*
+ * The IPv6 interface binder class
+ */
+
+CDummyIf6::CDummyIf6(CDummyIfLink& aLink)
+	: CNifIfBase(aLink)
+	{
+	CDummyIfLog::Printf(_L("CDummyIf6::CDummyIf6()"));
+
+	iLink = &aLink;
+
+	//
+	// Use the 64 bit id of MARM machines as our interface id
+	//
+	TMachineInfoV1Buf machineInfo;
+
+	UserHal::MachineInfo(machineInfo);
+	iLocalIfId.SetAddr(machineInfo().iMachineUniqueId);
+	iLocalIfId.SetUniversalBit(0);
+
+	//
+	// In WINS environment the id is zero which is no-no
+	//
+	if (iLocalIfId.IsZero())
+		iLocalIfId.SetAddrRandomNZ();
+
+	iIfName.Format(_L("dummynif6[0x%08x]"), this);
+	}
+
+void CDummyIf6::BindL(TAny *aId)
+	{
+	CDummyIfLog::Printf(_L("CDummyIf6::BindL(aId %x)"), aId);
+	if(iProtocol)
+		User::Leave(KErrAlreadyExists);
+	iProtocol = (CProtocolBase*)aId;	
+	}
+
+TInt CDummyIf6::Send(RMBufChain& aPdu, TAny*)
+	{
+	Recv(aPdu);
+	return 1;
+	}
+
+TInt CDummyIf6::State()
+    {
+    return EIfUp;
+    }
+
+void CDummyIf6::UpdateHeaders(TInet6HeaderIP* aIp6, TInet6HeaderUDP* /*aUdp*/)
+{
+	// swap over the destination and source addresses
+	TIp6Addr temp;
+	temp = aIp6->SrcAddr();
+	aIp6->SetSrcAddr(aIp6->DstAddr());
+	aIp6->SetDstAddr(temp);
+}
+
+void CDummyIf6::Recv(RMBufChain& aPdu)
+	{
+
+	TInt res;
+
+	// this received data has already been looped back...
+	// get the ip header from the RMBufChain
+	TInet6HeaderIP* ip6 = (TInet6HeaderIP*) aPdu.First()->Next()->Ptr();
+	TInet6HeaderUDP* udp = NULL;
+
+	if ((TUint)ip6->NextHeader() == KProtocolInetUdp)
+		{
+		// get the udp header as well - assume only udp traffic here
+		udp = (TInet6HeaderUDP*) ip6->EndPtr();
+
+		CDummyIfLog::Printf(_L("CDummyIf6::Recv(...): UDP length %d, src port %d, dst port %d"),
+			udp->Length(), udp->SrcPort(), udp->DstPort());
+
+		// depending on the contents, pass it on up thru the stack 
+		// or maybe do something else
+
+		// use the destination port number to decide whether or not the payload is a command
+		TUint dstPort = udp->DstPort();
+		if (KDummyNifCmdPort == dstPort)
+			{	
+			// let's use the first payload byte as the command byte
+			switch (*(udp->EndPtr()))
+				{
+			case KForceDisconnect:
+				CDummyIfLog::Printf(_L("KForceDisconnect command"));
+				// do some action
+				iNotify->IfProgress(KLinkLayerClosed, KErrCommsLineFail);
+				iNotify->LinkLayerDown(KErrCommsLineFail, MNifIfNotify::EDisconnect);
+				// no return code so all we can do is respond with what we got
+				UpdateHeaders(ip6, udp);
+				iProtocol->Process(aPdu, (CProtocolBase*)this);
+				break;
+
+			case KForceReconnect:
+				CDummyIfLog::Printf(_L("KForceReconnect command"));
+				// do some action
+				iNotify->IfProgress(KLinkLayerClosed, KErrCommsLineFail);
+				iNotify->LinkLayerDown(KErrCommsLineFail, MNifIfNotify::EReconnect);
+				// no return code so all we can do is respond with what we got
+				UpdateHeaders(ip6, udp);
+				iProtocol->Process(aPdu, (CProtocolBase*)this);
+				break;
+
+			case KSendNotification:
+				CDummyIfLog::Printf(_L("KSendNotification command"));
+				res = iNotify->Notification(ENifToAgentEventTypeQueryIsDialIn);
+				//let's write the result in the next byte of the reply
+				if (res == KErrNotSupported)
+					udp->EndPtr()[1] = (unsigned char) KErrNone;
+				else
+					udp->EndPtr()[1] = (unsigned char) KErrGeneral; // this will lose it's sign :-(
+				
+				UpdateHeaders(ip6, udp);
+				iProtocol->Process(aPdu, (CProtocolBase*)this);
+				break;
+
+			default:
+				CDummyIfLog::Printf(_L("Unknown command - ignoring it"));
+				break;
+				// unknown command, just ignore this packet???
+				}
+			return;
+			}
+
+		}
+	else
+		{
+		CDummyIfLog::Printf(_L("CDummyIf6::Recv(...): IPv6 length %d, next header %d"),
+			ip6->PayloadLength(), ip6->NextHeader());
+		}
+
+	// just echo the packet back to the original sender
+
+	// update the headers (addresses, checksums etc).  If "udp" is non-NULL, then
+	// the UDP ports will be updated as well.
+	UpdateHeaders(ip6, udp);
+	// now process it (pass up the stack)
+	iProtocol->Process(aPdu, (CProtocolBase*)this);		
+}
+
+void CDummyIf6::Info(TNifIfInfo& aInfo) const
+	{
+	aInfo.iVersion = TVersion(1,1,1);
+	aInfo.iFlags = KNifIfIsBase | KNifIfUsesNotify | KNifIfCreatedByLink;
+	aInfo.iName.Copy(iIfName);
+	aInfo.iProtocolSupported = 0;
+	}
+
+TInt CDummyIf6::Control(TUint aLevel, TUint aName, TDes8& aOption, TAny* /* aSource */)
+	{
+
+	if (aLevel==KSOLInterface)
+		{
+		switch (aName)
+			{
+		case KSoIfInfo6:
+			{
+			CDummyIfLog::Printf(_L("CDummyIf6::Control(KSOLInterface, KSoIfInfo6, ...)"));
+			__ASSERT_DEBUG((TUint)aOption.MaxLength() >= sizeof (TSoIfInfo6), User::Panic(_L("Dummy6"), 0));
+
+			if ((TUint)aOption.MaxLength() < sizeof (TSoIfInfo6))
+				return KErrArgument;
+
+			TSoIfInfo6& opt = *(TSoIfInfo6*)aOption.Ptr();
+			opt.iFeatures = KIfCanBroadcast | KIfCanMulticast;
+			opt.iName.Copy(iIfName);
+			opt.iMtu = 1500;
+			opt.iRMtu = opt.iMtu;
+			opt.iSpeedMetric = 0;
+
+			return KErrNone;
+			}
+
+		case KSoIfHardwareAddr:
+			return KErrNotSupported;
+
+		case KSoIfConfig:
+			{
+			CDummyIfLog::Printf(_L("CDummyIf6::Control(KSOLInterface, KSoIfConfig, ...)"));
+			__ASSERT_DEBUG((TUint)aOption.MaxLength() >= sizeof (TSoInet6IfConfig), User::Panic(_L("Dummy6"), 0));
+
+			if ((TUint)aOption.MaxLength() < sizeof (TSoInet6IfConfig))
+				return KErrArgument;
+
+			TSoInet6IfConfig& opt = *(TSoInet6IfConfig*)aOption.Ptr();
+			if (opt.iFamily != KAfInet6)
+				return KErrNotSupported;
+
+			TEui64Addr* ifId = (TEui64Addr*)&opt.iLocalId;
+
+			ifId->Init();
+			ifId->SetAddress(iLocalIfId);
+
+			ifId = (TEui64Addr*)&opt.iRemoteId;
+			ifId->Init();
+			ifId->SetAddress(iRemoteIfId);
+
+			// Setup static DNS address if required
+
+			if (!iPrimaryDns.IsUnspecified())
+				{
+				opt.iNameSer1.SetAddress(iPrimaryDns);
+				if (!iSecondaryDns.IsUnspecified())
+					opt.iNameSer2.SetAddress(iSecondaryDns);
+				}
+
+			opt.idPaddingBits = 0;
+			return KErrNone;
+			}
+
+		case KSoIfGetConnectionInfo:
+			{
+			CDummyIfLog::Printf(_L("CDummyIf6::Control(KSOLInterface, KSoIfGetConnectionInfo, ...)"));
+			TSoIfConnectionInfo& opt = *(TSoIfConnectionInfo*)aOption.Ptr();
+			TInt err = KErrNone;
+			TBuf<2*KCommsDbSvrMaxColumnNameLength+1> fieldName;
+			_LIT(KSlashChar, "\\");
+
+			fieldName.Copy(TPtrC(IAP));
+			fieldName.Append(KSlashChar);
+			fieldName.Append(TPtrC(COMMDB_ID));
+			if ((err = iNotify->ReadInt(fieldName, opt.iIAPId)) != KErrNone)
+				return err;
+
+			fieldName.Copy(TPtrC(IAP));
+			fieldName.Append(KSlashChar);
+			fieldName.Append(TPtrC(IAP_NETWORK));
+			if ((err = iNotify->ReadInt(fieldName, opt.iNetworkId)) != KErrNone)
+				return err;
+
+			return KErrNone;
+			}
+		default:
+			CDummyIfLog::Printf(_L("CDummyIf6::Control(KSOLInterface, aName %x, ...)"), aName);
+			break;
+			}
+		}
+	else
+		{
+		CDummyIfLog::Printf(_L("CDummyIf6::Control(aLevel %x, aName %x, ...)"), aLevel, aName);
+		}
+	return KErrNotSupported;
+	}
+
+TInt CDummyIf6::Notification(TAgentToNifEventType /*aEvent*/, void * /*aInfo*/)
+	{
+	return KErrNone;
+	}
+
+void CDummyIf6::StaticDnsConfiguration()
+	{
+	TBool requestDynamicDNSAddress;
+	// See whether we are configured to request a dynamic DNS address.
+	if (iNotify->ReadBool(TPtrC(SERVICE_IP6_DNS_ADDR_FROM_SERVER), requestDynamicDNSAddress) != KErrNone)
+		{
+		// Default behaviour
+		requestDynamicDNSAddress = ETrue;
+		}
+
+	if(!requestDynamicDNSAddress)
+		{
+		// Setup static DNS addresses from CommDb
+		CDummyIfLog::Printf(_L("CDummyIf6: Configuring static DNS addresses"));
+		PresetAddr(iPrimaryDns, TPtrC(SERVICE_IP6_NAME_SERVER1));
+		PresetAddr(iSecondaryDns, TPtrC(SERVICE_IP6_NAME_SERVER2));
+		}
+	else
+		{
+		// Ensure that static DNS addresses are set as unspecified,
+		// so they are not used in Control(KSoIfConfig).
+		iPrimaryDns = KInet6AddrNone;
+		iSecondaryDns = KInet6AddrNone;
+		}
+	}
+
+TInt CDummyIf6::PresetAddr(TIp6Addr& aAddr, const TDesC& aVarName)
+/**
+ * Preset IP adress in aAddr with value from CommDB. The field name
+ * is given in aVarName. Examples are "IpAddr" and "IpNameServer1"
+ *
+ * @param aAddr    IP address to be set
+ * @param aVarName name of CommDB field
+ * @return KErrNone if success, global error code otherwise
+ */
+	{
+	if (!aAddr.IsUnspecified())
+		return KErrNone;
+	
+	TBuf<KCommsDbSvrMaxFieldLength> name;
+
+	(void)iNotify->ReadDes(aVarName, name); // ignore return value
+	TInetAddr ip6Addr;
+
+	TInt ret = ip6Addr.Input(name);
+	if (ret == KErrNone)
+		{
+		aAddr = ip6Addr.Ip6Address();
+		}
+	return ret;
+	}