--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/networkprotocols/tcpipv4v6prt/src/ip6_doh.cpp Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,217 @@
+// 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:
+// ip6_doh.cpp - hooks for IPv6 protocol message options
+// Default IPv6 Options Hooks (Hop-by-Hop and Destination Options)
+//
+
+#include "ip6_doh.h"
+#include <in_pkt.h>
+#include <ext_hdr.h>
+#include <icmp6_hdr.h>
+#include "addr46.h"
+#include "inet6log.h"
+//
+// *NOTE*
+// With the autumn 2000 hook api changes, there is no reason
+// allocate two different objects for DOP and HBH. The same
+// object could handle both and bind for both. This is
+// because aInfo.iProtocol can now be used to differentiate
+// the two, if needed! -- msa [for future cleanup..]
+//
+// CDestinationOptionsHook::ConstructL
+//
+void CDestinationOptionsHook::ConstructL()
+ {
+ iProtocol->BindL((CProtocolBase *)this, BindHookFor(KProtocolInet6DestinationOptions));
+ }
+//
+// CHopOptionsHook::ConstructL
+//
+void CHopOptionsHook::ConstructL()
+ {
+ iProtocol->BindL((CProtocolBase *)this, BindHookFor(KProtocolInet6HopOptions));
+ }
+
+//
+// CDefaultOptionsHook::ApplyL
+// ***************************
+// The default Options processing (code shared by Destination Options and
+// Hop-by-Hop Options).
+//
+TInt CDefaultOptionsHook::ApplyL(RMBufHookPacket &aPacket, RMBufRecvInfo &aInfo)
+ {
+ if (aInfo.iVersion == 4)
+ {
+ //
+ // Do not process HBH or DOP for IPv4. Returning PASS
+ // will cause the main loop eventually to treat this
+ // as unknown header, if nothing else handles it.
+ //
+ return KIp6Hook_PASS;
+ }
+ for (;;) // .. just for exits.. not a loop..
+ {
+ TInet6Packet<TInet6Options> oh(aPacket, aInfo.iOffset);
+ if (oh.iHdr == NULL)
+ break; // Bad packet, not enough for even the basic header
+ const TInt hdrlen = aInfo.CheckL(oh.iHdr->HeaderLength());
+ const TInt next_header = oh.iHdr->NextHeader();
+
+ if (aInfo.iIcmp == 0)
+ {
+ //
+ // Normal Option Header Handling
+ //
+ TInt count = hdrlen - TInet6Options::O_Options; // Count of bytes in actual options.
+ TInt start = aInfo.iOffset + TInet6Options::O_Options; // Offset of the first
+ //
+ // Possibly heavy overhead, brute RMBuf Goto application
+ // (but should work always)
+ //
+ while (count > 0)
+ {
+ RMBuf *p;
+ TInt offset, len;
+ TUint8 *ptr, type;
+
+ if (!aPacket.Goto(start, p, offset, len))
+ goto drop_packet;
+ ptr = p->Buffer() + offset;
+ switch ((type = *ptr++))
+ {
+ case 0: // Pad1
+ count--;
+ start++;
+ break;
+#if 0
+ case KDstOptionHomeAddress:
+ if (aInfo.iProtocol == STATIC_CAST(TInt, KProtocolInet6DestinationOptions) &&
+ // ..just check that there is enough stuff in the buffer
+ // for the IPv6 address, so that the following CopyOut
+ // does not panic. If not, just fall through. Should
+ // do some better validity checking someday -- msa
+ STATIC_CAST(TUint, count) >= sizeof(TIp6Addr)+2)
+ {
+ // This is shared between DOP and HBH, but this option is only
+ // accepted in the DestinationOptions. The home address value
+ // is simply copied to the aInfo.iDstAddr!
+ //
+ TIp6Addr home;
+ TPtr8 ptr(home.u.iAddr8, sizeof(home.u.iAddr8), sizeof(home.u.iAddr8));
+
+ aPacket.CopyOut(ptr, start+2);
+ TInetAddr::Cast(aInfo.iSrcAddr).SetAddress(home);
+#ifdef _LOG
+ {
+ TBuf<70> tmp_src;
+ TInetAddr::Cast(aInfo.iSrcAddr).OutputWithScope(tmp_src);
+ Log::Printf(_L("CDefaultOptionsHook::ApplyL: HOMEADDRESS src=[%S]\r\n"), &tmp_src);
+ }
+#endif
+ aInfo.iFlags &= ~KIpAddressVerified; // Request Address Check!
+ goto skip_option;
+ }
+#endif
+ // If not handled, fall unknown option handling!
+ default:
+ //
+ // Unknown options
+ //
+ // 11 - send ICMP only if not Multicast dst
+ // 10 - send ICMP
+ // 01 - drop without ICMP
+ // 00 - skip and continue
+ //
+ // (use HookValue with keyid=(protocol | (type << 8)) to check if someone else
+ // already handled/implemented this option!)
+ //
+ if ((type & 0xC0) != 0 && aPacket.HookValue(aInfo.iProtocol | (type << 8)) == 0)
+ {
+ type &= 0xC0;
+ if (type == 0xC0)
+ {
+ if (TIp46Addr::Cast(TInetAddr::Cast(aInfo.iDstAddr).Ip6Address()).IsMulticast())
+ goto drop_packet;
+ }
+ else if (type != 0x80)
+ goto drop_packet;
+ //
+ // Either 11 without multicast or 10, send ICMP6 Parameter Promblem,
+ //
+ iProtocol->Icmp6Send(aPacket, KInet6ICMP_ParameterProblem, 2, start, 1 /* Allow MC destination */);
+ return -1;
+ }
+ //
+ // 00 - Skip Over
+ //
+ // ** FALL THROUGH TO THE PadN handling, skip option **
+ case 1: // PadN
+#if 0
+skip_option:
+#endif
+ --len;
+ while (len == 0) // Should loop only once, but 'while' just in
+ // case someone wants RMBuf with zero length...
+ {
+ p = p->Next();
+ if (p == NULL)
+ goto drop_packet;
+ len = p->Length();
+ ptr = p->Ptr();
+ }
+ count -= 2 + *ptr;
+ start += 2 + *ptr;
+ break;
+ }
+ }
+ // Fall to "header processed"!
+ }
+ else if (aInfo.iIcmp == KProtocolInet6Icmp)
+ {
+ //
+ // ICMP6 Problem report for a packet
+ //
+ const TInt offset = aInfo.iOffset - aInfo.iOffsetIp; // Relative offset within problem packet
+
+ if (aInfo.iType == KInet6ICMP_ParameterProblem && // A parameter problem...
+ offset <= (TInt)aInfo.iParameter && // after start of this header?
+ offset + hdrlen > (TInt)aInfo.iParameter) // and before end of this header?
+ break; // Drop!
+ // Fall to "header processed"!
+ }
+ else
+ {
+ //
+ // ICMP v4 problem report (or something else)
+ //
+ // * just drop it for now*
+ //
+ break;
+ }
+ //
+ // Gets Here only if the header is "processed" successfully
+ // Remove options header, pass error processing to the next header
+ //
+ aInfo.iPrevNextHdr = (TUint16)aInfo.iOffset; // Dest. Opt next header is at +0
+ aInfo.iProtocol = next_header;
+ aInfo.iOffset += hdrlen;
+ return KIp6Hook_DONE;
+ }
+ //
+ // All breakouts from the above "loop" cause the packet to be dropped
+ //
+drop_packet:
+ aPacket.Free();
+ return -1;
+ }