--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/networkprotocols/dnsproxy/dnsproxyserver/src/dnsproxymsgproc.cpp Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,540 @@
+// Copyright (c) 2008-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:
+// dnsproxymessageproc.cpp
+// This class constructs the response packet for matched query packet that
+// it gets from the queue. First it will get the name from the database
+// checks against the query name. If it matched then generates the answer for
+// query packet and appends into buffer then sends to querying host. Otherwise
+// generates the authoritive answer and sends back to querying hosts.
+//
+
+
+
+/**
+ @file
+ @internalTechnology
+*/
+
+
+#include <e32base.h>
+#include <e32math.h>
+#include <e32des8.h>
+#include <e32debug.h>
+#include <utf.h>
+#include "dns_qry_internal.h"
+#include "inet6log.h"
+
+#include "dnsproxymsgproc.h"
+#include "dnsproxylistener.h"
+#include "dnsproxyengine.h"
+#include "message.h"
+#include "dnsproxylog.h"
+
+
+CDnsProxyMessageProcessor* CDnsProxyMessageProcessor::NewL(CDnsProxyListener& aListener)
+/**
+ * This is the two phase construction method and is leaving function
+ * @param aListener - reference CDnsProxyListener class
+ *
+ * @internalTechnology
+ **/
+
+ {
+ CDnsProxyMessageProcessor* response = new(ELeave) CDnsProxyMessageProcessor(aListener);
+ return response;
+ }
+
+CDnsProxyMessageProcessor::CDnsProxyMessageProcessor(CDnsProxyListener& aListener):iListener(aListener),iAntype(0)
+/**
+ * This is the constructor for this class
+ * @param aListener - reference CDnsProxyListener class
+ * @return - None
+ *
+ * @internalTechnology
+ **/
+
+ {
+ }
+
+CDnsProxyMessageProcessor::~CDnsProxyMessageProcessor()
+/**
+ * This is the destructor and deletes all the member variables and thus
+ * releases all the memory assosicated with those objects
+ * @param - None
+ * @return - None
+ *
+ * @internalTechnology
+ **/
+ {
+ }
+
+void CDnsProxyMessageProcessor::GetDnsFailureMessage(TMsgBuf& aMsgBuf)
+/**
+ * This is create DNS Failure message
+
+ * @param - TMsgBuf&
+ * @return - None
+ *
+ * @internalTechnology
+ **/
+ {
+ TDndHeader &hdr = aMsgBuf.Header();
+
+ hdr.SetQR(1);
+ //set dns server failure
+ hdr.SetRCode(2);
+ }
+
+void CDnsProxyMessageProcessor::GetLocalDnsResponseL(TMsgBuf& aMsgbuf)
+/**
+ * This function constructs the response packet. First it gets the
+ * only query name by filtering the qtype and qclass then it tries to
+ * match the names. If it matches then, generates the ANResource reord
+ * otherwise generates the NSResource Record.
+ * @param -aMsg - Query packet
+ * @internalTechnology
+ **/
+
+ {
+ TDndQuestion qDns;
+ qDns.Create(aMsgbuf, sizeof(TDndHeader));
+
+ TBuf<KDnsMaxName> queryName;
+ TInt ret_val = qDns.GetName(queryName);
+ if(ret_val==KErrNone)
+ {
+ HBufC8* q_name = CnvUtfConverter::ConvertFromUnicodeToUtf8L(queryName);
+ CleanupStack::PushL(q_name);
+
+ TPtrC8 qname = q_name->Right(q_name->Length());
+ EDnsQType iQType = qDns.QType();
+
+ switch(qDns.QType())
+ {
+ case EDnsQType_A:
+ {
+ TDnsProxydbElement* element;
+ TDndHeader& hdr = aMsgbuf.Header();
+ CDnsProxyEngine& engine = iListener.GetDnsProxyEngine();
+
+ element = engine.iDnsproxydb->GetRecordList(qname);
+ if(element)
+ {
+ hdr.SetNsCount(0);
+ GetRecordsFromDb(aMsgbuf,*element);
+ }
+ else
+ {
+ SetQHeaderBits(hdr);
+ hdr.SetNsCount(1);
+ GetNsRecordSetL(aMsgbuf);
+ }
+ }
+ break;
+ case EDnsQType_PTR:
+ {
+ TDnsProxydbElement* element = NULL;
+ element = LookupPTRInDb(aMsgbuf);
+ if(element)
+ {
+ GetPTRRecord(aMsgbuf,element->iHostName);
+ }
+ }
+ break;
+ }
+ CleanupStack::PopAndDestroy(q_name);
+ }
+ }
+
+void CDnsProxyMessageProcessor::SetQHeaderBits(TDndHeader& aHdr)
+/**
+ * This will set bits fileds of query header as required for
+ * response message
+ * @param aHdr - reference to header section of query
+ * @internalTechnology
+ **/
+
+ {
+ TInt aId = aHdr.ID();
+ aHdr.SetId(aId);
+ aHdr.SetQR(1);
+ aHdr.SetOpcode(0);
+ aHdr.SetAA(0);
+ aHdr.SetRCode(0);
+
+ TInt qdcount = aHdr.QDCOUNT();
+ aHdr.SetQdCount(qdcount);
+ aHdr.SetArCount(0);
+ }
+
+void CDnsProxyMessageProcessor::GetRecordsFromDb(TMsgBuf& aMsg,TDnsProxydbElement& aElement)
+/**
+ * This will give constructed response message for given query
+ * @param aMsg - query
+ * @param - aElement - reference to TDnsProxydbElement class
+ * @internalTechnology
+ *
+ **/
+ {
+ iAntype =0;
+ TDndHeader &hdr = aMsg.Header();
+ SetQHeaderBits(hdr);
+ TInt hdr_id = hdr.ID();
+
+ if(aElement.iRecord.Length()==0)
+ {
+ GetAnRecordSet(aMsg,aElement);
+ }
+ else
+ {
+ TBuf8<KDnsMaxMessage>record;
+ record = aElement.iRecord;
+ aMsg = TMsgBuf::Cast(record);
+ TDndHeader& header = aMsg.Header();
+ TInt hdid = header.ID();
+ LOG(Log::Printf(_L("\t \n --- Transaction Id:[%d]"),hdid));
+ header.SetId(hdr_id);
+ TUint16 qtype = aElement.iDnsQType;
+ if(qtype==EDnsType_A)
+ iAntype++;
+ }
+ hdr.SetAnCount(iAntype);
+
+ hdr.SetNsCount(0);
+ }
+
+void CDnsProxyMessageProcessor::GetAnRecordSet(TMsgBuf& aQMsg,TDnsProxydbElement& aElement)
+/**
+ * Constructs answer resource record/s and appends it to buffer
+ * @param - aQMsg, dns query message
+ * @param - aElement, reference to TDnsProxydbElement class
+ * @leave - system wide errors, buffer overflow
+ * @internalTechnology
+ **/
+ {
+ CDnsProxyEngine& engine = iListener.GetDnsProxyEngine();
+
+ aQMsg.Header();
+
+ TInetAddr address = aElement.iHostAddr;
+
+ THostName name;
+ aQMsg.GetName(sizeof(aQMsg.Header()),name);
+
+
+ TDndQuestion question;
+ TInt index = question.Create(aQMsg,sizeof(aQMsg.Header()));
+
+ TInt len = aQMsg.Length();
+
+ TDndRROut rrout(aQMsg);
+
+ TDnsProxyConfigParams iEngineConfig = iListener.GetDnsProxyEngine().GetConfig();
+ rrout.iType = (TUint16)question.QType();
+ rrout.iClass = (TUint16)question.QClass();
+ rrout.iTTL = iEngineConfig.iTTL;
+ TInt ret = rrout.Append(KNullDesC8, sizeof(TDndHeader));
+ iAntype++;
+ rrout.AppendRData(address);
+
+ engine.iDnsproxydb->AddRRecord(aElement,aQMsg,question.QType());
+
+ }
+
+void CDnsProxyMessageProcessor::GetNsRecordSetL(TMsgBuf& aMsg)
+/**
+ * constructs and appends the authoritive resource records
+ * @param - aQMsg, dns query message
+ * @leave - system wide errors, buffer overflow
+ *
+ * @internalTechnology
+ **/
+ {
+ TDnsProxyNsRecord nsrecord;
+ TBuf8<KDnsMaxMessage> record;
+
+ //read from TTL from config
+ CDnsProxyEngine& engine = iListener.GetDnsProxyEngine();
+ TUint ttl = engine.GetConfig().iTTL;
+ //Create RBuf
+ RBuf8 qname;
+
+ TInt offset = sizeof(TDndHeader);
+ const TUint8* ptr = (aMsg.Ptr() + offset);
+ TPtrC8 ptrc8(aMsg.Ptr() + offset, aMsg.Size() - offset);
+
+ qname.Create(ptrc8.Size());
+ CleanupClosePushL(qname);
+
+ qname.Copy(TPtrC8(&ptr[0],ptrc8.Size()));
+
+ nsrecord.ResetBuffer();
+ nsrecord.iQType = EDnsType_SOA;
+ nsrecord.iCType = EDnsClass_IN;
+ nsrecord.iTTL = ttl;
+ nsrecord.iSerialNum = engine.iConfigParams.iSerialNum;
+ nsrecord.iRefreshTime = engine.iConfigParams.iRefreshTime;
+ nsrecord.iRetryTime = engine.iConfigParams.iRetryTime;
+ nsrecord.iExpiretime = engine.iConfigParams.iExpiretime;
+
+ record = nsrecord.CreateNSResourceRecord(qname);
+ aMsg.Append(record);
+ CleanupStack::PopAndDestroy(&qname);
+ }
+
+TInt CDnsProxyMessageProcessor::GetQNameSuffixL(TMsgBuf& aMsg)
+/**
+ * This function gets the suffix of recieved query
+ * @param aMsg - reference to dns query message
+ * @return ret_val - represents whether query is local or global query
+ *
+ * @internalTechnology
+ **/
+ {
+ CDnsProxyEngine& engine = iListener.GetDnsProxyEngine();
+
+ TInt retVal = KGlobalQuery;
+
+ /*In case suffix information is not available
+ treat it as global query no need of comparison*/
+ if(!engine.IsSuffixAvailable())
+ return retVal;
+ TDndQuestion qDns;
+ qDns.Create(aMsg, sizeof(TDndHeader));
+ EDnsQType iQType = qDns.QType();
+
+ switch (qDns.QType())
+ {
+ case EDnsQType_A:
+ {
+ TBuf<KMaxName> buf;
+ buf.Copy(engine.iSuffixInfo);
+ HBufC8* nsuffix = CnvUtfConverter::ConvertFromUnicodeToUtf8L(buf);
+ CleanupStack::PushL(nsuffix);
+ TPtrC8 qsuffix = nsuffix->Right(nsuffix->Length());
+ TBuf<KDnsMaxName> queryName;
+ TInt err = qDns.GetName(queryName);
+ if(err == KErrNone)
+ {
+ HBufC8* new_name = CnvUtfConverter::ConvertFromUnicodeToUtf8L(queryName);
+ TPtrC8 qname = new_name->Right(new_name->Length());
+ if(qname.Length() > qsuffix.Length())
+ {
+ TPtrC8 suffix = qname.Mid((qname.Length())-(qsuffix.Length()),qsuffix.Length());
+ TInt errVal = suffix.Compare(qsuffix);
+ if(errVal==KErrNone)
+ {
+ retVal = KLocalQuery;
+ __LOG("Processing Local Query-Type-A");
+ }
+ else
+ __LOG("Processing Global Query-Type-A");
+ }
+
+ delete new_name;
+ }
+ CleanupStack::PopAndDestroy(nsuffix);
+ }
+ break;
+ case EDnsQType_PTR:
+ {
+ TDnsProxydbElement* element = NULL;
+ element = LookupPTRInDb(aMsg);
+ if(element)
+ {
+ retVal = KLocalQuery;
+ }
+ else
+ {
+ retVal = KGlobalQuery;
+ }
+ }
+ break;
+ default:
+ {
+ retVal = KGlobalQuery;
+ }
+
+ } // end switch
+ return retVal;
+ }
+TDnsProxydbElement* CDnsProxyMessageProcessor::LookupPTRInDb(TMsgBuf& aMsg)
+/**
+* Looksup in db for existance of the recod. If present then process query as local
+* otherwise treats PTR query as a global one
+* @param aMsg - Query Message
+* @return TDnsProxydbElement - pointer to TDnsProxydbElement object
+*
+**/
+ {
+ CDnsProxyEngine& engine = iListener.GetDnsProxyEngine();
+
+ TBuf<KPTRSufix>ptrbuf;
+ ptrbuf.Copy(KPTRSUFFIX);
+
+ TDndQuestion qDns;
+ qDns.Create(aMsg, sizeof(TDndHeader));
+
+ TBuf<KDnsMaxName> queryName;
+ TInt flag = qDns.GetName(queryName);
+
+ TDnsProxydbElement* element = NULL;
+ if(queryName.Length()>ptrbuf.Length())
+ {
+ TPtrC16 ipaddr = queryName.Mid(0,(queryName.Length()-(ptrbuf.Length()+1)));
+ TInetAddr address;
+ address.Input(ipaddr);
+ TUint32 ad = address.Address();
+ TUint32 swapaddr =(((ad&0x000000FF)<<24)+((ad&0x0000FF00)<<8)+
+ ((ad&0x00FF0000)>>8)+((ad&0xFF000000)>>24));
+ TInetAddr inetaddr;
+ inetaddr.SetAddress(swapaddr);
+
+ element = engine.iDnsproxydb->FindIpAddress(inetaddr);
+ }
+
+ return element;
+ }
+void CDnsProxyMessageProcessor::GetPTRRecord(TMsgBuf& aMsg,const TDesC8& aName)
+/**
+* Constructs PTR record and appends to TMsgBuf
+* @param aMsg - Query Message
+* @param aElement - reference to TDnsProxydbElement class which matched to query name
+*
+* @internalTechnology
+**/
+ {
+ TDndHeader &hdr = aMsg.Header();
+
+ SetQHeaderBits(hdr);
+ hdr.SetAA(1);
+ hdr.SetAnCount(1);
+
+ TDndQuestion question;
+ TInt index = question.Create(aMsg,sizeof(TDndHeader));
+
+ TInt len = aMsg.Length();
+
+ TDndRROut rrout(aMsg);
+
+ rrout.iType = (TUint16)question.QType();
+ rrout.iClass = (TUint16)question.QClass();
+
+ rrout.iTTL = iListener.GetDnsProxyEngine().GetConfig().iTTL;
+ TInt ret = rrout.Append(KNullDesC8, sizeof(TDndHeader));
+
+ TInt err = rrout.AppendRData(aName,0);
+ }
+TDesC8& TDnsProxyNsRecord::CreateNSResourceRecord(const TDesC8& aMsg)
+/**
+ * Creates new authorative answer record for given query. This will be
+ * generated when ther is no matching name found in db
+ * @param aMsg - Dns query
+ * @return iNSBuf - buffer having constructed authorative answer record
+ *
+ * @internalTechnology
+ **/
+ {
+
+ TInt offset_pos = aMsg.Locate(0);
+ const TUint8* ptr8 = (aMsg.Ptr());
+ TBufC8<KDnsMaxMessage> abuf_ns = TPtrC8(&ptr8[0],offset_pos);
+
+ iNSBuf.Append(abuf_ns);
+ //this will identify the termination of the QName
+ iNSBuf.Append((TChar)0);
+
+ iNSBuf.Append(iQType/0x100);
+ iNSBuf.Append(iQType%0x100);
+
+ iNSBuf.Append(iCType/0x100);
+ iNSBuf.Append(iCType%0x100);
+ AppendTTLBuf();
+ AppendRRLength(aMsg);
+
+ return iNSBuf;
+ }
+
+void TDnsProxyNsRecord::AppendTTLBuf()
+/**
+ * Appends the TTL to ns record set
+ *
+ * @internalTechnology
+ **/
+ {
+ iNSBuf.Append((TChar)(iTTL / 0x1000000));
+ iNSBuf.Append((TChar)((iTTL / 0x10000) % 0x100));
+ iNSBuf.Append((TChar)((iTTL / 0x100) % 0x100));
+ iNSBuf.Append((TChar)(iTTL % 0x100));
+ }
+
+void TDnsProxyNsRecord::AppendRRLength(const TDesC8& aMsg)
+/**
+ * This function creates the NS Resource Record as specified in
+ * the RFC1035 section 3.3.13.-SOA RDATA Format
+ * @param - aMsg ,reference to buf which will have ns record set
+ *
+ * @internalTechnology
+ **/
+ {
+ TBuf8<KDnsMaxMessage> buf;
+ buf.Append(aMsg);
+ buf.Append((TChar)0);
+ buf.Append(aMsg);
+ buf.Append((TChar)0);
+
+ buf.Append((TChar)(iSerialNum / 0x1000000));
+ buf.Append((TChar)((iSerialNum / 0x10000) % 0x100));
+ buf.Append((TChar)((iSerialNum / 0x100) % 0x100));
+ buf.Append((TChar)(iSerialNum % 0x100));
+
+ buf.Append((TChar)(iRefreshTime / 0x1000000));
+ buf.Append((TChar)((iRefreshTime / 0x10000) % 0x100));
+ buf.Append((TChar)((iRefreshTime / 0x100) % 0x100));
+ buf.Append((TChar)(iRefreshTime % 0x100));
+
+ buf.Append((TChar)(iRetryTime / 0x1000000));
+ buf.Append((TChar)((iRetryTime / 0x10000) % 0x100));
+ buf.Append((TChar)((iRetryTime / 0x100) % 0x100));
+ buf.Append((TChar)(iRetryTime % 0x100));
+
+ buf.Append((TChar)(iExpiretime / 0x1000000));
+ buf.Append((TChar)((iExpiretime / 0x10000) % 0x100));
+ buf.Append((TChar)((iExpiretime / 0x100) % 0x100));
+ buf.Append((TChar)(iExpiretime % 0x100));
+
+ buf.Append((TChar)(iTTL / 0x1000000));
+ buf.Append((TChar)((iTTL / 0x10000) % 0x100));
+ buf.Append((TChar)((iTTL / 0x100) % 0x100));
+ buf.Append((TChar)(iTTL % 0x100));
+
+ TInt len = buf.Size();
+ iNSBuf.Append((TChar)(len/0x0100));
+ iNSBuf.Append((TChar)(len%0x0100));
+
+ iNSBuf.Append(buf);
+
+ }
+
+void TDnsProxyNsRecord::ResetBuffer()
+/**
+ * before appending anything newly, deletes its contents first then append
+ *
+ * @internalTechnology
+ **/
+ {
+ TInt len = iNSBuf.Length();
+ if(len>0)
+ iNSBuf.Delete(0,len);
+ }