--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/bluetoothcommsprofiles/btpan/pannapiphook/src/pannapiphook.cpp Fri Jan 15 08:13:17 2010 +0200
@@ -0,0 +1,201 @@
+// Copyright (c) 2007-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:
+//
+
+#include <bluetooth/logger.h>
+#include "pannapiphook.h"
+#include "RBnepFrame.h" // For the DHCP / Forwarding RMBufPacket header flags
+
+#include <in_sock.h>
+#include <in_chk.h>
+#include <udp_hdr.h>
+#include <es_prot_internal.h>
+
+_LIT(KProtocolPanNapIpHookName, "pannapiphook");
+
+#ifdef __FLOG_ACTIVE
+_LIT8(KLogComponent, LOG_COMPONENT_PAN_NAPIPHOOK);
+#endif
+
+#ifdef __FLOG_ACTIVE
+// Define strings for logging.
+_LIT(KStringTrue, "True");
+_LIT(KStringFalse, "False");
+_LIT(KStringDropped, "Dropped");
+_LIT(KStringPassed, "Passed");
+#endif
+
+
+static const TUint KDhcpDstPort = 67;
+
+// Returning a negative number from the ApplyL() method in an IP hook will make the IP
+// stack drop the packet. No constant is defined in networking so define it here to
+// help readability of the code.
+static const TInt KIp6Hook_DROP = -1;
+
+//
+// CPanNapIpHook
+//
+CPanNapIpHook* CPanNapIpHook::NewL()
+ {
+ CPanNapIpHook* self = new(ELeave) CPanNapIpHook();
+ return self;
+ }
+
+CPanNapIpHook::~CPanNapIpHook()
+ {
+ Unbind(this,BindHookAll());
+ CProtocolPosthook::NetworkDetached();
+ }
+
+void CPanNapIpHook::NetworkAttachedL()
+ {
+ // This hook is dual purpose and checks both that incoming packets destined for the
+ // DHCP server and any packets to be forwarded to the uplink have access to do so.
+ // This is why the hook gets bound in 2 places, once for forwarding packets and once
+ // for all incoming packets. The logic in ApplyL() determines where the hook has
+ // been called from.
+ NetworkService()->BindL(this, BindForwardHook());
+ NetworkService()->BindL(this, BindHookAll());
+ iManager = NetworkService()->Interfacer();
+ }
+
+TInt CPanNapIpHook::ApplyL(RMBufHookPacket &aPacket, RMBufRecvInfo &aInfo)
+ {
+ TInt rCode = KIp6Hook_PASS;
+
+ // This hook is for packets coming from BNEP only and performs two purposes depending
+ // on whether or not the packet is destined for the local host or not.
+ if(aInfo.iFlags & KBnep)
+ {
+ LOG1(_L("Remote device granted access to uplink: %S"), (aInfo.iFlags & KBnepForwardingAllowed) ? &KStringTrue() : &KStringFalse());
+
+ if (iManager->IsForMeAddress(TInetAddr::Cast(aInfo.iDstAddr).Ip6Address(), aInfo.iInterfaceIndex))
+ {
+ LOG(_L("Packet destined for local host"));
+
+ // Make sure that any packets from BNEP destined for the DHCP Server are processed
+ // only if it has come from a remote device granted access to the uplink
+ if(aInfo.iProtocol == KProtocolInetUdp)
+ {
+ TInet6Checksum<TInet6HeaderIP4> ipHeader(aPacket);
+ TInet6Packet<TInet6HeaderUDP> udpHeader(aPacket, ipHeader.iHdr->HeaderLength());
+
+ if(udpHeader.iHdr->DstPort() == KDhcpDstPort)
+ {
+ LOG(_L("DHCP packet detected"));
+
+ // DHCP packet. Drop if forwarding flag not set.
+ if(!(aInfo.iFlags & KBnepForwardingAllowed))
+ {
+ aPacket.Free();
+ rCode = KIp6Hook_DROP; // Drop packet
+ }
+ }
+ }
+ }
+ else
+ {
+ LOG(_L("Packet destined to be forwarded"));
+
+ // Before forwarding packets from BNEP ensure that they have come from a remote
+ // device granted access to the uplink
+ if(!(aInfo.iFlags & KBnepForwardingAllowed))
+ {
+ aPacket.Free();
+ rCode = KIp6Hook_DROP; // Drop packet
+ }
+ }
+ }
+
+ // Finished with the flags
+ aInfo.iFlags &= ~KBnep;
+ aInfo.iFlags &= ~KBnepForwardingAllowed;
+
+ LOG1(_L("Packet %S"), (rCode < 0) ? &KStringDropped() : &KStringPassed());
+
+ return rCode;
+ }
+
+void CPanNapIpHook::Identify(TServerProtocolDesc* aProtocolDesc) const
+ {
+ Describe(*aProtocolDesc);
+ }
+
+void CPanNapIpHook::Describe(TServerProtocolDesc& aEntry)
+ {
+ aEntry.iName = KProtocolPanNapIpHookName;
+ aEntry.iAddrFamily = KAfInet;
+ aEntry.iSockType = KSockDatagram;
+ aEntry.iProtocol = KProtocolPanNapIpHook;
+ aEntry.iVersion = TVersion(1, 0, 0);
+ aEntry.iByteOrder = EBigEndian;
+ aEntry.iServiceInfo = KSIDatagram | KSIConnectionLess;
+ aEntry.iNamingServices = 0;
+ aEntry.iSecurity = KSocketNoSecurity;
+ aEntry.iMessageSize = 0xffff;
+ aEntry.iServiceTypeInfo = 0;
+ aEntry.iNumSockets = KUnlimitedSockets;
+ aEntry.iServiceTypeInfo = ESocketSupport | EInterface;
+ }
+
+//
+// CPanNapIpHookFamily
+//
+CPanNapIpHookFamily::CPanNapIpHookFamily()
+ {
+ __DECLARE_NAME(_S("CPanNapIpHookFamily"));
+ }
+
+CPanNapIpHookFamily::~CPanNapIpHookFamily()
+ {
+ }
+
+TInt CPanNapIpHookFamily::Install()
+ {
+ return KErrNone;
+ }
+
+TInt CPanNapIpHookFamily::Remove()
+ {
+ return KErrNone;
+ }
+
+TUint CPanNapIpHookFamily::ProtocolList(TServerProtocolDesc *& aProtocolList)
+ {
+ aProtocolList = new TServerProtocolDesc[1];
+
+ if (!aProtocolList)
+ {
+ return 0;
+ }
+
+ CPanNapIpHook::Describe(aProtocolList[0]);
+ return 1;
+ }
+
+CProtocolBase* CPanNapIpHookFamily::NewProtocolL(TUint /*aSockType*/, TUint aProtocol)
+ {
+ if (aProtocol != KProtocolPanNapIpHook)
+ {
+ User::Leave(KErrNotSupported);
+ }
+ return CPanNapIpHook::NewL();
+ }
+
+EXPORT_C CProtocolFamilyBase* Install(void)
+ {
+ CPanNapIpHookFamily* protocol = new CPanNapIpHookFamily();
+ return protocol;
+ }