networkprotocols/tcpipv4v6prt/src/ip6_rth.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 // ip6_rth.cpp - default hook for IPv6 routing header
       
    15 //
       
    16 
       
    17 #include <ext_hdr.h>
       
    18 #include "ip6_rth.h"
       
    19 #include <in_pkt.h>
       
    20 #include <icmp6_hdr.h>
       
    21 #include "addr46.h"
       
    22 //
       
    23 // CRoutingHeaderHook::InitL
       
    24 //
       
    25 void CRoutingHeaderHook::ConstructL()
       
    26 	{
       
    27 	iProtocol->BindL(this, BindHookFor(KProtocolInet6RoutingHeader));
       
    28 	}
       
    29 
       
    30 //
       
    31 // CRoutingHeaderHook::ApplyL
       
    32 //
       
    33 //
       
    34 TInt CRoutingHeaderHook::ApplyL(RMBufHookPacket &aPacket, RMBufRecvInfo &aInfo)
       
    35 	{
       
    36 	if (aInfo.iVersion == 4)
       
    37 		{
       
    38 		//
       
    39 		// Do not process RTH for IPv4. Returning PASS
       
    40 		// will cause the main loop eventually to treat this
       
    41 		// as unknown header, if nothing else handles it.
       
    42 		//
       
    43 		return KIp6Hook_PASS;
       
    44 		}
       
    45 
       
    46 	for (;;)	// .. just for easy error exits with "break"!
       
    47 		{
       
    48 		TInet6Packet<TInet6HeaderRouting> rt(aPacket, aInfo.iOffset);
       
    49 		if (rt.iHdr == NULL)
       
    50 			break;			// Not enough for even the basic part, drop packet!
       
    51 		//
       
    52 		const TInt hdrlen = aInfo.CheckL(rt.iHdr->HeaderLength());
       
    53 		const TInt next_header = rt.iHdr->NextHeader();
       
    54 		//
       
    55 		// The iIcmp decides whether this is a normal Routing Header or
       
    56 		// some error report relating to such...
       
    57 		//
       
    58 		if (aInfo.iIcmp == 0)
       
    59 			{
       
    60 			TInt left = rt.iHdr->SegmentsLeft(); // Always >= 0!
       
    61 			if (left == 0)
       
    62 				{
       
    63 				//
       
    64 				// Remove routing header
       
    65 				//
       
    66 				aInfo.iProtocol = next_header;
       
    67 				aInfo.iPrevNextHdr = (TUint16)aInfo.iOffset;	// Next Header is at +0 in RTH.
       
    68 				aInfo.iOffset += hdrlen;
       
    69 				return KIp6Hook_DONE;
       
    70 				}
       
    71 
       
    72 			if (rt.iHdr->RoutingType() != 0)
       
    73 				{
       
    74 				// Unknown routing type, with segments left > 0! Must send
       
    75 				// parameter problem, Code = 0 and point to type.
       
    76 				//
       
    77 				iProtocol->Icmp6Send(aPacket, KInet6ICMP_ParameterProblem, 0,
       
    78 					aInfo.iOffset + TInet6HeaderRouting::O_RoutingType);
       
    79 				return -1;
       
    80 				}
       
    81 
       
    82 			TInt extlen = rt.iHdr->HdrExtLen();	// Always >= 0!
       
    83 			if (extlen & 1)
       
    84 				{
       
    85 				//
       
    86 				// Odd length, need to send ICMP parameter problem, Code = 0
       
    87 				// and point to Hdr Ext Len.
       
    88 				// --- not correct, if we allowed RTH within IPv4! -- msa
       
    89 				iProtocol->Icmp6Send(aPacket, KInet6ICMP_ParameterProblem, 0,
       
    90 					aInfo.iOffset + TInet6HeaderRouting::O_HdrExtLen);
       
    91 				return -1;
       
    92 				}
       
    93 			extlen >>= 1;	// = number of addresses
       
    94 			extlen -= left;	// index of the next address
       
    95 			if (extlen < 0)
       
    96 				{
       
    97 				// --- not correct, if we allowed RTH within IPv4! -- msa
       
    98 				iProtocol->Icmp6Send(aPacket, KInet6ICMP_ParameterProblem, 0,
       
    99 					aInfo.iOffset + TInet6HeaderRouting::O_SegmentsLeft);
       
   100 				return -1;
       
   101 				}
       
   102 			rt.iHdr->SetSegmentsLeft(left-1);
       
   103 			extlen = (extlen << 3) + TInet6HeaderRouting::O_Address;	// = offset to the address.
       
   104 
       
   105 			TIp6Addr address;
       
   106 			TPtr8 ptr((TUint8 *)(&address), sizeof(TIp6Addr), sizeof(TIp6Addr));
       
   107 			aPacket.CopyOut(ptr, aInfo.iOffset + extlen);
       
   108 			if (ptr.Length() != sizeof(TIp6Addr))
       
   109 				break;	// Bad Packet
       
   110 			if (TIp46Addr::Cast(address).IsMulticast() ||
       
   111 				TIp46Addr::Cast(TInetAddr::Cast(aInfo.iDstAddr).Ip6Address()).IsMulticast())
       
   112 				break;	// Bad RTH! Send ICMP ?
       
   113 			//
       
   114 			// Do the address swap
       
   115 			// -- update IPv6 header (destination address)
       
   116 			aPacket.CopyIn(ptr, aInfo.iOffsetIp + TInet6HeaderIP::O_DstAddr);
       
   117 			// -- swap info dest and routing header
       
   118 			ptr.Set((TUint8 *)&(TInetAddr::Cast(aInfo.iDstAddr).Ip6Address()), sizeof(TIp6Addr), sizeof(TIp6Addr));
       
   119 			aPacket.CopyIn(ptr, aInfo.iOffset + extlen);
       
   120 			TInetAddr::Cast(aInfo.iDstAddr).SetAddress(address);
       
   121 
       
   122 			// HopLimit decrements from here, because it is automaticly
       
   123 			// decreased by the forwarding action. However, if the address from
       
   124 			// the routing header is still for this host, then hoplimit does not
       
   125 			// affect it. Should it? Does this break any RFC? -- msa
       
   126 	
       
   127 			//
       
   128 			// All done, resubmit by leaving the header in
       
   129 			//
       
   130 			aInfo.iFlags &= ~KIpAddressVerified;	// Force destination address check!
       
   131 			return KIp6Hook_DONE;
       
   132 			}
       
   133 		else if (aInfo.iIcmp == KProtocolInet6Icmp)
       
   134 			{
       
   135 			//
       
   136 			// ICMP6 Error report
       
   137 			//
       
   138 			const TInt offset = aInfo.iOffset - aInfo.iOffsetIp;// Relative offset within problem packet
       
   139 
       
   140 			if (aInfo.iType == KInet6ICMP_ParameterProblem &&	// A parameter problem...
       
   141 				offset <= (TInt)aInfo.iParameter &&		// after start of this header?
       
   142 				offset + hdrlen > (TInt)aInfo.iParameter)	// and before end of this header?
       
   143 				break;	// ICMP Paremeter error in routing header, just drop for now.
       
   144 			//
       
   145 			// Remove routing header, pass error processing to the next header
       
   146 			//
       
   147 			aInfo.iPrevNextHdr = (TUint16)aInfo.iOffset;	// next_header is at +0 in RTH!
       
   148 			aInfo.iProtocol = next_header;
       
   149 			aInfo.iOffset += hdrlen;
       
   150 			return KIp6Hook_DONE;
       
   151 			}
       
   152 		//
       
   153 		// ICMP4 Error report (or something weird)
       
   154 		//
       
   155 		// * just drop it*
       
   156 		//
       
   157 		break;
       
   158 		}
       
   159 	//
       
   160 	// On any problem, get here and do the drop packet return
       
   161 	//
       
   162 	aPacket.Free();
       
   163 	return -1;
       
   164 	};