diff -r 000000000000 -r af10295192d8 networkprotocols/tcpipv4v6prt/src/ip6_rth.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/networkprotocols/tcpipv4v6prt/src/ip6_rth.cpp Tue Jan 26 15:23:49 2010 +0200 @@ -0,0 +1,164 @@ +// 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_rth.cpp - default hook for IPv6 routing header +// + +#include +#include "ip6_rth.h" +#include +#include +#include "addr46.h" +// +// CRoutingHeaderHook::InitL +// +void CRoutingHeaderHook::ConstructL() + { + iProtocol->BindL(this, BindHookFor(KProtocolInet6RoutingHeader)); + } + +// +// CRoutingHeaderHook::ApplyL +// +// +TInt CRoutingHeaderHook::ApplyL(RMBufHookPacket &aPacket, RMBufRecvInfo &aInfo) + { + if (aInfo.iVersion == 4) + { + // + // Do not process RTH 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 easy error exits with "break"! + { + TInet6Packet rt(aPacket, aInfo.iOffset); + if (rt.iHdr == NULL) + break; // Not enough for even the basic part, drop packet! + // + const TInt hdrlen = aInfo.CheckL(rt.iHdr->HeaderLength()); + const TInt next_header = rt.iHdr->NextHeader(); + // + // The iIcmp decides whether this is a normal Routing Header or + // some error report relating to such... + // + if (aInfo.iIcmp == 0) + { + TInt left = rt.iHdr->SegmentsLeft(); // Always >= 0! + if (left == 0) + { + // + // Remove routing header + // + aInfo.iProtocol = next_header; + aInfo.iPrevNextHdr = (TUint16)aInfo.iOffset; // Next Header is at +0 in RTH. + aInfo.iOffset += hdrlen; + return KIp6Hook_DONE; + } + + if (rt.iHdr->RoutingType() != 0) + { + // Unknown routing type, with segments left > 0! Must send + // parameter problem, Code = 0 and point to type. + // + iProtocol->Icmp6Send(aPacket, KInet6ICMP_ParameterProblem, 0, + aInfo.iOffset + TInet6HeaderRouting::O_RoutingType); + return -1; + } + + TInt extlen = rt.iHdr->HdrExtLen(); // Always >= 0! + if (extlen & 1) + { + // + // Odd length, need to send ICMP parameter problem, Code = 0 + // and point to Hdr Ext Len. + // --- not correct, if we allowed RTH within IPv4! -- msa + iProtocol->Icmp6Send(aPacket, KInet6ICMP_ParameterProblem, 0, + aInfo.iOffset + TInet6HeaderRouting::O_HdrExtLen); + return -1; + } + extlen >>= 1; // = number of addresses + extlen -= left; // index of the next address + if (extlen < 0) + { + // --- not correct, if we allowed RTH within IPv4! -- msa + iProtocol->Icmp6Send(aPacket, KInet6ICMP_ParameterProblem, 0, + aInfo.iOffset + TInet6HeaderRouting::O_SegmentsLeft); + return -1; + } + rt.iHdr->SetSegmentsLeft(left-1); + extlen = (extlen << 3) + TInet6HeaderRouting::O_Address; // = offset to the address. + + TIp6Addr address; + TPtr8 ptr((TUint8 *)(&address), sizeof(TIp6Addr), sizeof(TIp6Addr)); + aPacket.CopyOut(ptr, aInfo.iOffset + extlen); + if (ptr.Length() != sizeof(TIp6Addr)) + break; // Bad Packet + if (TIp46Addr::Cast(address).IsMulticast() || + TIp46Addr::Cast(TInetAddr::Cast(aInfo.iDstAddr).Ip6Address()).IsMulticast()) + break; // Bad RTH! Send ICMP ? + // + // Do the address swap + // -- update IPv6 header (destination address) + aPacket.CopyIn(ptr, aInfo.iOffsetIp + TInet6HeaderIP::O_DstAddr); + // -- swap info dest and routing header + ptr.Set((TUint8 *)&(TInetAddr::Cast(aInfo.iDstAddr).Ip6Address()), sizeof(TIp6Addr), sizeof(TIp6Addr)); + aPacket.CopyIn(ptr, aInfo.iOffset + extlen); + TInetAddr::Cast(aInfo.iDstAddr).SetAddress(address); + + // HopLimit decrements from here, because it is automaticly + // decreased by the forwarding action. However, if the address from + // the routing header is still for this host, then hoplimit does not + // affect it. Should it? Does this break any RFC? -- msa + + // + // All done, resubmit by leaving the header in + // + aInfo.iFlags &= ~KIpAddressVerified; // Force destination address check! + return KIp6Hook_DONE; + } + else if (aInfo.iIcmp == KProtocolInet6Icmp) + { + // + // ICMP6 Error report + // + 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; // ICMP Paremeter error in routing header, just drop for now. + // + // Remove routing header, pass error processing to the next header + // + aInfo.iPrevNextHdr = (TUint16)aInfo.iOffset; // next_header is at +0 in RTH! + aInfo.iProtocol = next_header; + aInfo.iOffset += hdrlen; + return KIp6Hook_DONE; + } + // + // ICMP4 Error report (or something weird) + // + // * just drop it* + // + break; + } + // + // On any problem, get here and do the drop packet return + // + aPacket.Free(); + return -1; + };