networkprotocols/ipeventnotifier/src/DHCPUnicastTranslator.cpp
changeset 0 af10295192d8
child 37 052078dda061
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/networkprotocols/ipeventnotifier/src/DHCPUnicastTranslator.cpp	Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,147 @@
+// Copyright (c) 2006-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:
+//
+
+/**
+ @file DHCPUnicastTranslator.cpp
+ @internalComponent
+*/
+
+#include <in_chk.h>
+#include <in_sock.h>
+#include <in_bind.h>
+#include "in6_opt.h"
+#include <udp_hdr.h>
+
+#include "DHCPUnicastTranslator.h"
+#include "HookLog.h"
+#include "ipeventlistener.h"
+
+
+
+
+CDHCPUnicastTranslator::CDHCPUnicastTranslator(CProtocolInet6Binder& aParent):
+	iParent(aParent)
+	{
+	}
+		
+CDHCPUnicastTranslator::~CDHCPUnicastTranslator()
+	{
+//	iParent.Unbind(this, 0);
+	}
+
+void CDHCPUnicastTranslator::FillIdentification(TServerProtocolDesc& anEntry)
+/**
+ * Fills in an existing protocol description structure with details of this protocol.
+ *
+ * @param aProtocolDesc: reference to the structure to be filled in
+ */
+	{
+	anEntry.iName=_S("dhcpunicasttranslator");
+	anEntry.iAddrFamily=KAfInet;
+	anEntry.iSockType=0;
+	anEntry.iProtocol=1; // not in a family so doesn't really matter
+	anEntry.iVersion=TVersion(1, 0, 0);
+	anEntry.iByteOrder=EBigEndian;
+	anEntry.iServiceInfo=0;
+	anEntry.iNamingServices=0;
+	anEntry.iSecurity=0;
+	anEntry.iMessageSize=0;
+	anEntry.iServiceTypeInfo=0;
+	anEntry.iNumSockets=0;
+	}
+
+
+void CDHCPUnicastTranslator::Identify(TServerProtocolDesc* aProtocolDesc) const
+/**
+ * Fills in an existing protocol description structure with details of this protocol.
+ *
+ * @param aProtocolDesc: pointer to the structure to be filled in
+ */
+	{
+	FillIdentification(*aProtocolDesc);
+	}
+
+
+
+/**
+ * Incoming packet
+ */
+TInt CDHCPUnicastTranslator::ApplyL(RMBufHookPacket& aPacket, RMBufRecvInfo& aInfo)
+	{
+
+	LOG	(
+		_LIT(KHookNotifyStr,"CDHCPUnicastTranslator::ApplyL hit with protocol: %d");
+		HookLog::Printf( KHookNotifyStr , aInfo.iProtocol );
+		)
+	
+	/** Fix for INC079832 - DHCP must be able to receive unicast replies from
+	 *   DHCP server (to an address that hasn't been set yet! chicken and egg).
+	 *
+	 *  Without this, a DHCP reply unicast to an address which isn't yet assigned
+	 *   to the inbound interface will be dropped.
+	 *
+	 *  So we need to detect BOOTP packets which are about to be dropped. This is
+	 *   done by installing this object as a "forwarding hook".
+	 *
+	 *  DHCP packets are detected as follows:
+	 *   - packet is UDP
+	 *   - UDP destination port is 0x0044
+	 *
+	 *  Modification is performed by setting dest address to broadcast address
+	 *   (and updating checksum)
+	 *
+	 *  Then we return KIp6Hook_DONE (which signals to the stack to re-inject
+	 *   the packet into the incoming data path).
+	 *
+	 *  Note: this trick isn't needed for IPv6 as link-local unicast is always
+	 *   possible before network/global address has been assigned.
+	 */
+    if (aInfo.iVersion != 4 || aInfo.iProtocol != KProtocolInetUdp)
+        return KIp6Hook_PASS;    // Only interested in IPv4 and UDP.
+
+    TInetAddr&  dst = TInetAddr::Cast(aInfo.iDstAddr);
+
+    if (!dst.IsUnicast())
+        return KIp6Hook_PASS;    // Only the unicast case really needs fixing
+
+    // Need to examine the UDP header
+    TInet6Packet<TInet6HeaderUDP> udp(aPacket, aInfo.iOffset);
+    if (udp.iHdr == NULL)
+        return KIp6Hook_PASS;    // Oops, short packet, let someone else worry about it.
+
+    // To cause least distruption, one could try to check that this really is
+    // DCHP address configuration message with packet destination address
+    // matching the offered address inside DCHP message (but this would need
+    // more extensive packet snooping here)    
+#ifndef _DEBUG
+    if (udp.iHdr->DstPort() == 68)
+#else
+	if (udp.iHdr->DstPort() == 68 || udp.iHdr->DstPort() == 127 || udp.iHdr->DstPort() == 119 || udp.iHdr->DstPort() == 125
+	#ifdef SYMBIAN_NETWORKING_DHCP_MSG_HEADERS
+	|| udp.iHdr->DstPort() == 92 || udp.iHdr->DstPort() == 99
+	#endif//SYMBIAN_NETWORKING_DHCP_MSG_HEADERS	
+	)	// debug mode, src port 127, 119, 125, 91, 98
+#endif
+        {
+        static const TIp6Addr broadcast = {{{0,0,0,0,0,0,0,0,0,0,0xff,0xff,255,255,255,255}}};
+
+        dst.SetAddress(broadcast);
+        udp.iHdr->SetChecksum(0);    // Either this or recompute the UDP checksum for broadcast address.
+        return KIp6Hook_DONE;
+        }
+    return KIp6Hook_PASS;
+	}
+
+