diff -r 000000000000 -r af10295192d8 networkprotocols/dnsproxy/dnsproxyserver/src/dnsproxymsgproc.cpp --- /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 +#include +#include +#include +#include +#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 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 + { + TBuf8record; + 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 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 buf; + buf.Copy(engine.iSuffixInfo); + HBufC8* nsuffix = CnvUtfConverter::ConvertFromUnicodeToUtf8L(buf); + CleanupStack::PushL(nsuffix); + TPtrC8 qsuffix = nsuffix->Right(nsuffix->Length()); + TBuf 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(); + + TBufptrbuf; + ptrbuf.Copy(KPTRSUFFIX); + + TDndQuestion qDns; + qDns.Create(aMsg, sizeof(TDndHeader)); + + TBuf 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 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 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); + }