networkprotocols/tcpipv4v6prt/src/ip6_doh.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_doh.cpp - hooks for IPv6 protocol message options
       
    15 // Default IPv6 Options Hooks (Hop-by-Hop and Destination Options)
       
    16 //
       
    17 
       
    18 #include "ip6_doh.h"
       
    19 #include <in_pkt.h>
       
    20 #include <ext_hdr.h>
       
    21 #include <icmp6_hdr.h>
       
    22 #include "addr46.h"
       
    23 #include "inet6log.h"
       
    24 //
       
    25 // *NOTE*
       
    26 //		With the autumn 2000 hook api changes, there is no reason
       
    27 //		allocate two different objects for DOP and HBH. The same
       
    28 //		object could handle both and bind for both. This is
       
    29 //		because aInfo.iProtocol can now be used to differentiate
       
    30 //		the two, if needed! -- msa [for future cleanup..]
       
    31 //
       
    32 // CDestinationOptionsHook::ConstructL
       
    33 //
       
    34 void CDestinationOptionsHook::ConstructL()
       
    35 	{
       
    36 	iProtocol->BindL((CProtocolBase *)this, BindHookFor(KProtocolInet6DestinationOptions));
       
    37 	}
       
    38 //
       
    39 // CHopOptionsHook::ConstructL
       
    40 //
       
    41 void CHopOptionsHook::ConstructL()
       
    42 	{
       
    43 	iProtocol->BindL((CProtocolBase *)this, BindHookFor(KProtocolInet6HopOptions));
       
    44 	}
       
    45 
       
    46 //
       
    47 //	CDefaultOptionsHook::ApplyL
       
    48 //	***************************
       
    49 //	The default Options processing (code shared by Destination Options and
       
    50 //	Hop-by-Hop Options).
       
    51 //
       
    52 TInt CDefaultOptionsHook::ApplyL(RMBufHookPacket &aPacket, RMBufRecvInfo &aInfo)
       
    53 	{
       
    54 	if (aInfo.iVersion == 4)
       
    55 		{
       
    56 		//
       
    57 		// Do not process HBH or DOP for IPv4. Returning PASS
       
    58 		// will cause the main loop eventually to treat this
       
    59 		// as unknown header, if nothing else handles it.
       
    60 		//
       
    61 		return KIp6Hook_PASS;
       
    62 		}
       
    63 	for (;;)	// .. just for exits.. not a loop..
       
    64 		{
       
    65 		TInet6Packet<TInet6Options> oh(aPacket, aInfo.iOffset);
       
    66 		if (oh.iHdr == NULL)
       
    67 			break;	// Bad packet, not enough for even the basic header
       
    68 		const TInt hdrlen = aInfo.CheckL(oh.iHdr->HeaderLength());
       
    69 		const TInt next_header = oh.iHdr->NextHeader();
       
    70 
       
    71 		if (aInfo.iIcmp == 0)
       
    72 			{
       
    73 			//
       
    74 			// Normal Option Header Handling
       
    75 			//
       
    76 			TInt count = hdrlen - TInet6Options::O_Options;			// Count of bytes in actual options.
       
    77 			TInt start = aInfo.iOffset + TInet6Options::O_Options;	// Offset of the first
       
    78 			//
       
    79 			// Possibly heavy overhead, brute RMBuf Goto application
       
    80 			// (but should work always)
       
    81 			//
       
    82 			while (count > 0)
       
    83 				{
       
    84 				RMBuf *p;
       
    85 				TInt offset, len;
       
    86 				TUint8 *ptr, type;
       
    87 
       
    88 				if (!aPacket.Goto(start, p, offset, len))
       
    89 					goto drop_packet;
       
    90 				ptr = p->Buffer() + offset;
       
    91 				switch ((type = *ptr++))
       
    92 					{
       
    93 				case 0:	// Pad1
       
    94 					count--;
       
    95 					start++;
       
    96 					break;
       
    97 #if 0
       
    98 				case KDstOptionHomeAddress:
       
    99 					if (aInfo.iProtocol == STATIC_CAST(TInt, KProtocolInet6DestinationOptions) &&
       
   100 						// ..just check that there is enough stuff in the buffer
       
   101 						// for the IPv6 address, so that the following CopyOut
       
   102 						// does not panic. If not, just fall through. Should
       
   103 						// do some better validity checking someday -- msa
       
   104 						STATIC_CAST(TUint, count) >= sizeof(TIp6Addr)+2)
       
   105 						{
       
   106 						// This is shared between DOP and HBH, but this option is only
       
   107 						// accepted in the DestinationOptions. The home address value
       
   108 						// is simply copied to the aInfo.iDstAddr!
       
   109 						//
       
   110 						TIp6Addr home;
       
   111 						TPtr8 ptr(home.u.iAddr8, sizeof(home.u.iAddr8), sizeof(home.u.iAddr8));
       
   112 
       
   113 						aPacket.CopyOut(ptr, start+2);
       
   114 						TInetAddr::Cast(aInfo.iSrcAddr).SetAddress(home);
       
   115 #ifdef _LOG
       
   116 							{
       
   117 							TBuf<70> tmp_src;
       
   118 							TInetAddr::Cast(aInfo.iSrcAddr).OutputWithScope(tmp_src);
       
   119 							Log::Printf(_L("CDefaultOptionsHook::ApplyL: HOMEADDRESS src=[%S]\r\n"), &tmp_src);
       
   120 							}
       
   121 #endif
       
   122 						aInfo.iFlags &= ~KIpAddressVerified;		// Request Address Check!
       
   123 						goto skip_option;
       
   124 						}
       
   125 #endif
       
   126 					// If not handled, fall unknown option handling!
       
   127 				default:
       
   128 					//
       
   129 					// Unknown options
       
   130 					//
       
   131 					// 11 - send ICMP only if not Multicast dst
       
   132 					// 10 - send ICMP
       
   133 					// 01 - drop without ICMP
       
   134 					// 00 - skip and continue
       
   135 					//
       
   136 					// (use HookValue with keyid=(protocol | (type << 8)) to check if someone else
       
   137 					// already handled/implemented this option!)
       
   138 					//
       
   139 					if ((type & 0xC0) != 0 && aPacket.HookValue(aInfo.iProtocol | (type << 8)) == 0)
       
   140 						{
       
   141 						type &= 0xC0;
       
   142 						if (type == 0xC0)
       
   143 							{
       
   144 							if (TIp46Addr::Cast(TInetAddr::Cast(aInfo.iDstAddr).Ip6Address()).IsMulticast())
       
   145 								goto drop_packet;
       
   146 							}
       
   147 						else if (type != 0x80)
       
   148 							goto drop_packet;
       
   149 						//
       
   150 						// Either 11 without multicast or 10, send ICMP6 Parameter Promblem,
       
   151 						//
       
   152 						iProtocol->Icmp6Send(aPacket, KInet6ICMP_ParameterProblem, 2, start, 1 /* Allow MC destination */);
       
   153 						return -1;
       
   154 						}
       
   155 					//
       
   156 					// 00 - Skip Over
       
   157 					//
       
   158 					// ** FALL THROUGH TO THE PadN handling, skip option **
       
   159 				case 1:	// PadN
       
   160 #if 0
       
   161 skip_option:
       
   162 #endif
       
   163 					--len;
       
   164 					while (len == 0)	// Should loop only once, but 'while' just in
       
   165 										// case someone wants RMBuf with zero length...
       
   166 						{
       
   167 						p = p->Next();
       
   168 						if (p == NULL)
       
   169 							goto drop_packet;
       
   170 						len = p->Length();
       
   171 						ptr = p->Ptr();
       
   172 						}
       
   173 					count -= 2 + *ptr;
       
   174 					start += 2 + *ptr;
       
   175 					break;
       
   176 					}
       
   177 				}
       
   178 			// Fall to "header processed"!
       
   179 			}
       
   180 		else if (aInfo.iIcmp == KProtocolInet6Icmp)
       
   181 			{
       
   182 			//
       
   183 			// ICMP6 Problem report for a packet
       
   184 			//
       
   185 			const TInt offset = aInfo.iOffset - aInfo.iOffsetIp;	// Relative offset within problem packet
       
   186 
       
   187 			if (aInfo.iType == KInet6ICMP_ParameterProblem &&	// A parameter problem...
       
   188 				offset <= (TInt)aInfo.iParameter &&			// after start of this header?
       
   189 				offset + hdrlen > (TInt)aInfo.iParameter)		// and before end of this header?
       
   190 				break;		// Drop!
       
   191 			// Fall to "header processed"!
       
   192 			}
       
   193 		else
       
   194 			{
       
   195 			//
       
   196 			// ICMP v4 problem report (or something else)
       
   197 			//
       
   198 			// * just drop it for now*
       
   199 			//
       
   200 			break;
       
   201 			}
       
   202 		//
       
   203 		// Gets Here only if the header is "processed" successfully
       
   204 		// Remove options header, pass error processing to the next header
       
   205 		//
       
   206 		aInfo.iPrevNextHdr = (TUint16)aInfo.iOffset;	// Dest. Opt next header is at +0
       
   207 		aInfo.iProtocol = next_header;
       
   208 		aInfo.iOffset += hdrlen;
       
   209 		return KIp6Hook_DONE;
       
   210 		}
       
   211 	//
       
   212 	// All breakouts from the above "loop" cause the packet to be dropped
       
   213 	//
       
   214 drop_packet:
       
   215 	aPacket.Free();
       
   216 	return -1;
       
   217 	}