networkprotocols/tcpipv4v6prt/src/icmp.cpp
changeset 0 af10295192d8
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // icmp.cpp - dual IPv4/IPv6 ICMP protocol
       
    15 // This implements two separate protocol modules (icmp and
       
    16 // icmp6). Unlike other transport layers (tcp and udp), ICMP has
       
    17 // different protocol identifier in IPv4 and IPv4. Thus, two separate
       
    18 // protocol instances is a requirement.
       
    19 //
       
    20 
       
    21 #include "inet6log.h"
       
    22 #include "icmp6.h"
       
    23 #include "in_net.h"
       
    24 #include <icmp6_hdr.h>
       
    25 #include <in_pkt.h>
       
    26 
       
    27 _LIT(KIcmpName, "icmp");
       
    28 _LIT(KIcmp6Name, "icmp6");
       
    29 
       
    30 //
       
    31 //	CProtocolICMP
       
    32 //	*************
       
    33 //	The implementation and methods of the CProtocolICMP4/6 is totally internal
       
    34 //	to this module. No other module needs to be aware of this.
       
    35 //	Thus the class definition is included here.
       
    36 //
       
    37 class CProtocolICMP : public CProtocolInet6Network
       
    38 	{
       
    39 public:
       
    40 	CProtocolICMP(TInt aProtocol);
       
    41 	virtual ~CProtocolICMP();
       
    42 	virtual CServProviderBase *NewSAPL(TUint aProtocol);
       
    43 	virtual void Process(RMBufChain &aPacket,CProtocolBase* aSourceProtocol=NULL);
       
    44 	virtual TInt Send(RMBufChain &aPacket,CProtocolBase* aSourceProtocol=NULL);
       
    45 	virtual void Identify(TServerProtocolDesc *) const;
       
    46 protected:
       
    47 	const TInt iProtocol;
       
    48 	};
       
    49 
       
    50 //	*****
       
    51 //	ICMP6
       
    52 //	*****
       
    53 CProtocolBase *ICMP6::NewL(TInt aVersion)
       
    54 	{
       
    55 	return new (ELeave) CProtocolICMP(aVersion);
       
    56 	}
       
    57 
       
    58 void ICMP6::Identify(TServerProtocolDesc &aEntry, TInt aVersion)
       
    59 	{
       
    60 	if (aVersion == STATIC_CAST(TInt, KProtocolInetIcmp))
       
    61 		{
       
    62 		aEntry.iName = KIcmpName;
       
    63 		aEntry.iProtocol=KProtocolInetIcmp;
       
    64 		}
       
    65 	else
       
    66 		{
       
    67 		aEntry.iName = KIcmp6Name;
       
    68 		aEntry.iProtocol=KProtocolInet6Icmp;
       
    69 		}
       
    70 	aEntry.iAddrFamily=KAfInet;
       
    71 	aEntry.iSockType=KSockDatagram;
       
    72 	aEntry.iVersion=TVersion(KInet6MajorVersionNumber, KInet6MinorVersionNumber, KInet6BuildVersionNumber);
       
    73 	aEntry.iByteOrder=EBigEndian;
       
    74 	aEntry.iServiceInfo=KICMP6ServiceInfo;
       
    75 	aEntry.iNamingServices=KICMP6NameServiceInfo;
       
    76 	aEntry.iSecurity=KSocketNoSecurity;
       
    77 	aEntry.iMessageSize=KICMP6MaxDatagramSize;
       
    78 	aEntry.iServiceTypeInfo=KICMP6ServiceTypeInfo;
       
    79 	aEntry.iNumSockets=KICMP6MaxSockets;
       
    80 	}
       
    81 
       
    82 //
       
    83 
       
    84 //
       
    85 //	CProtocolICMP* constructors and destructors
       
    86 //	*******************************************
       
    87 
       
    88 CProtocolICMP::CProtocolICMP(TInt aId) : iProtocol(aId)
       
    89 	{
       
    90 	__DECLARE_NAME(_S("CProtocolICMP"));
       
    91 	}
       
    92 
       
    93 CProtocolICMP::~CProtocolICMP()
       
    94 	{
       
    95 	}
       
    96 
       
    97 //
       
    98 // CProtocolICMP::NewSAPL
       
    99 //	Create a new instance of a CServProviderBase (SAP) for the
       
   100 //	socket manager. The caller is responsible for the bookkeeping
       
   101 //	and destruction of this created object!
       
   102 //
       
   103 CServProviderBase* CProtocolICMP::NewSAPL(TUint aSockType)
       
   104 	{
       
   105 	return ICMP6::NewSAPL(aSockType, this, iProtocol);
       
   106 	}
       
   107 
       
   108 void CProtocolICMP::Identify(TServerProtocolDesc *aInfo) const
       
   109 	{
       
   110 	ICMP6::Identify(*aInfo, iProtocol);
       
   111 	}
       
   112 
       
   113 //
       
   114 // CProtocolICMP::Send()
       
   115 //
       
   116 //	Pass the packet as is to the IP layer. This method is
       
   117 //	supposed to be used by the ICMP Service provider modules
       
   118 //	to forward their packets down the stack.
       
   119 //
       
   120 //	ICMP makes no checks on validity or format of the packet
       
   121 //
       
   122 TInt CProtocolICMP::Send(RMBufChain &aPacket,CProtocolBase* /*aSourceProtocol*/)
       
   123 	{
       
   124 	return iNetwork->Send(aPacket);
       
   125 	}
       
   126 
       
   127 
       
   128 void CProtocolICMP::Process(RMBufChain &aPacket,CProtocolBase * /*aSourceProtocol*/)
       
   129 	{
       
   130 	RMBufRecvPacket packet;
       
   131 	packet.Assign(aPacket);
       
   132 
       
   133 	for (;;) // ONLY FOR NEAT BREAK EXITS -- NOT A LOOP
       
   134 		{
       
   135 		RMBufRecvInfo *const info = packet.Unpack();
       
   136 		if (info == NULL)
       
   137 			break;
       
   138 
       
   139 		LOG(Log::Printf(_L("\t%S Process(%d bytes)"), &ProtocolName(), info->iLength));
       
   140 		if (info->iIcmp)
       
   141 			{
       
   142 			// This packet is actually an ICMP error report to an ICMP sent by
       
   143 			// this host. The iOffset points to "inner" ICMP, but tradionally
       
   144 			// ICMP applications expect the outer RAW ICMP's, thus, change
       
   145 			// the iOffset and other fields accordingly
       
   146 			info->iOffset = info->iOffsetIp - 8 /* 8 = ICMP header size*/;
       
   147 			info->iProtocol = info->iIcmp;
       
   148 			// *NOTE*
       
   149 			//	The following assumes that outer IP tunnels have been removed
       
   150 			//	from the packet. Then, it can be assumed that the IP header
       
   151 			//	related to ICMP error is at the beginning of the packet (offset=0).
       
   152 			info->iOffsetIp = 0;
       
   153 			const MInterface *const mi = NetworkService()->Interfacer()->Interface(info->iInterfaceIndex);
       
   154 			if (mi == NULL)
       
   155 				break;
       
   156 			TIpHeader *const ip = ((RMBufPacketPeek &)packet).GetIpHeader();
       
   157 			if (ip == NULL)
       
   158 				break;
       
   159 			TInetAddr &src = TInetAddr::Cast(info->iSrcAddr);
       
   160 			TInetAddr &dst = TInetAddr::Cast(info->iDstAddr);
       
   161 			if (ip->ip4.Version() == 4)
       
   162 				{
       
   163 				src.SetV4MappedAddress(ip->ip4.SrcAddr());
       
   164 				dst.SetV4MappedAddress(ip->ip4.DstAddr());
       
   165 				}
       
   166 			else
       
   167 				{
       
   168 				src.SetAddress(ip->ip6.SrcAddr());
       
   169 				dst.SetAddress(ip->ip6.DstAddr());
       
   170 				}
       
   171 			const TIp6Addr &src_ip = src.Ip6Address();
       
   172 			const TIp6Addr &dst_ip = dst.Ip6Address();
       
   173 			src.SetScope(mi->Scope((TScopeType)(src_ip.Scope()-1)));
       
   174 			dst.SetScope(mi->Scope((TScopeType)(dst_ip.Scope()-1)));
       
   175 			}
       
   176 
       
   177 		// Check "payload length", and don't even try delivering truncated ICMP packets.
       
   178 		if (info->iLength - info->iOffset < TInet6HeaderICMP::MinHeaderLength())
       
   179 			break;
       
   180 
       
   181 		Deliver(packet);
       
   182 		// *ALWAYS BREAK OUT FROM LOOP*
       
   183 		break;
       
   184 		}
       
   185 	packet.Free();
       
   186 	}