networkprotocols/dnsproxy/dnsproxyserver/src/dnsproxymsgproc.cpp
changeset 0 af10295192d8
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     1 // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // dnsproxymessageproc.cpp
       
    15 // This class constructs the response packet for matched query packet that
       
    16 // it gets from the queue. First it will get the name from the database
       
    17 // checks against the query name. If it matched then generates the answer for
       
    18 // query packet and appends into buffer then sends to querying host. Otherwise
       
    19 // generates the authoritive answer and sends back to querying hosts.
       
    20 //
       
    21 
       
    22 
       
    23 
       
    24 /**
       
    25  @file
       
    26  @internalTechnology
       
    27 */
       
    28 
       
    29 
       
    30 #include <e32base.h>
       
    31 #include <e32math.h>
       
    32 #include <e32des8.h> 
       
    33 #include <e32debug.h> 
       
    34 #include <utf.h>
       
    35 #include "dns_qry_internal.h"
       
    36 #include "inet6log.h"
       
    37 
       
    38 #include "dnsproxymsgproc.h"
       
    39 #include "dnsproxylistener.h"
       
    40 #include "dnsproxyengine.h"
       
    41 #include "message.h"
       
    42 #include "dnsproxylog.h"
       
    43 
       
    44 
       
    45 CDnsProxyMessageProcessor* CDnsProxyMessageProcessor::NewL(CDnsProxyListener& aListener)
       
    46 /**
       
    47  * This is the two phase construction method and is leaving function
       
    48  * @param aListener - reference CDnsProxyListener class
       
    49  *
       
    50  * @internalTechnology
       
    51  **/
       
    52 
       
    53 	{
       
    54 	CDnsProxyMessageProcessor* response = new(ELeave) CDnsProxyMessageProcessor(aListener);
       
    55 	return response;
       
    56 	}
       
    57 	
       
    58 CDnsProxyMessageProcessor::CDnsProxyMessageProcessor(CDnsProxyListener& aListener):iListener(aListener),iAntype(0)
       
    59 /**
       
    60  * This is the constructor for this class
       
    61  * @param aListener - reference CDnsProxyListener class
       
    62  * @return - None
       
    63  *
       
    64  * @internalTechnology
       
    65  **/
       
    66 
       
    67 	{
       
    68 	}
       
    69 
       
    70 CDnsProxyMessageProcessor::~CDnsProxyMessageProcessor()
       
    71 /**
       
    72  * This is the destructor  and deletes all the member variables and thus
       
    73  * releases all the memory assosicated with those objects
       
    74  * @param - None
       
    75  * @return - None
       
    76  *
       
    77  * @internalTechnology
       
    78  **/
       
    79 	{
       
    80 	}
       
    81 	
       
    82 void CDnsProxyMessageProcessor::GetDnsFailureMessage(TMsgBuf& aMsgBuf)
       
    83 /**
       
    84  * This is create DNS Failure message
       
    85  
       
    86  * @param - TMsgBuf&
       
    87  * @return - None
       
    88  *
       
    89  * @internalTechnology
       
    90  **/
       
    91 	{
       
    92 	TDndHeader &hdr = aMsgBuf.Header();
       
    93 	
       
    94 	hdr.SetQR(1);
       
    95 	//set dns server failure
       
    96 	hdr.SetRCode(2);
       
    97 	}
       
    98 	
       
    99 void CDnsProxyMessageProcessor::GetLocalDnsResponseL(TMsgBuf& aMsgbuf)
       
   100 /**
       
   101  * This function constructs the response packet. First it gets the 
       
   102  * only query name by filtering the qtype and qclass then it tries to
       
   103  * match the names. If it matches then, generates the ANResource reord 
       
   104  * otherwise generates the NSResource Record.
       
   105  * @param -aMsg - Query packet
       
   106  * @internalTechnology
       
   107  **/
       
   108 
       
   109 	{
       
   110 	TDndQuestion qDns;
       
   111 	qDns.Create(aMsgbuf, sizeof(TDndHeader));
       
   112 
       
   113 	TBuf<KDnsMaxName> queryName;
       
   114 	TInt ret_val = qDns.GetName(queryName);
       
   115 	if(ret_val==KErrNone)
       
   116 		{
       
   117 		HBufC8* q_name = CnvUtfConverter::ConvertFromUnicodeToUtf8L(queryName);
       
   118 		CleanupStack::PushL(q_name);
       
   119 		
       
   120 		TPtrC8 qname = q_name->Right(q_name->Length());
       
   121 		EDnsQType iQType = qDns.QType();
       
   122 				
       
   123 		switch(qDns.QType())
       
   124 			{
       
   125 				case EDnsQType_A:
       
   126 					{
       
   127 					TDnsProxydbElement* element;
       
   128 					TDndHeader& hdr = aMsgbuf.Header();
       
   129 					CDnsProxyEngine& engine = iListener.GetDnsProxyEngine();
       
   130 					
       
   131 					element = engine.iDnsproxydb->GetRecordList(qname);
       
   132 					if(element)
       
   133 						{
       
   134 						hdr.SetNsCount(0);
       
   135 						GetRecordsFromDb(aMsgbuf,*element);
       
   136 						}
       
   137 					else	
       
   138 						{
       
   139 						SetQHeaderBits(hdr);
       
   140 						hdr.SetNsCount(1);
       
   141 						GetNsRecordSetL(aMsgbuf);
       
   142 						}	
       
   143 					}
       
   144 					break;
       
   145 				case EDnsQType_PTR:
       
   146 					{
       
   147 					TDnsProxydbElement* element = NULL;
       
   148 					element = LookupPTRInDb(aMsgbuf);
       
   149 	                if(element)
       
   150 	                    {           
       
   151 	                    GetPTRRecord(aMsgbuf,element->iHostName);
       
   152 	                    }
       
   153 					}
       
   154 					break;
       
   155 			}
       
   156 			CleanupStack::PopAndDestroy(q_name);
       
   157 		}
       
   158 	}
       
   159 	
       
   160 void CDnsProxyMessageProcessor::SetQHeaderBits(TDndHeader& aHdr)
       
   161 /**
       
   162  * This will set bits fileds of query header as required for 
       
   163  * response message
       
   164  * @param aHdr - reference to header section of query
       
   165  * @internalTechnology
       
   166  **/	
       
   167 
       
   168 	{
       
   169 	TInt aId = aHdr.ID();
       
   170 	aHdr.SetId(aId);
       
   171 	aHdr.SetQR(1);
       
   172 	aHdr.SetOpcode(0);
       
   173 	aHdr.SetAA(0);
       
   174 	aHdr.SetRCode(0);
       
   175 
       
   176 	TInt qdcount = aHdr.QDCOUNT();
       
   177 	aHdr.SetQdCount(qdcount);
       
   178 	aHdr.SetArCount(0);
       
   179 	}
       
   180 	
       
   181 void CDnsProxyMessageProcessor::GetRecordsFromDb(TMsgBuf& aMsg,TDnsProxydbElement& aElement)
       
   182 /**
       
   183  * This will give constructed response message for given query
       
   184  * @param aMsg - query 
       
   185  * @param - aElement - reference to TDnsProxydbElement class
       
   186  * @internalTechnology
       
   187  *
       
   188  **/	
       
   189 	{
       
   190 	iAntype =0;
       
   191 	TDndHeader &hdr = aMsg.Header();
       
   192 	SetQHeaderBits(hdr);
       
   193 	TInt hdr_id = hdr.ID();
       
   194 
       
   195 	if(aElement.iRecord.Length()==0)
       
   196 		{
       
   197 		GetAnRecordSet(aMsg,aElement);
       
   198 		}
       
   199 	else
       
   200 		{
       
   201 		TBuf8<KDnsMaxMessage>record;
       
   202 		record = aElement.iRecord;
       
   203 		aMsg = TMsgBuf::Cast(record);
       
   204 		TDndHeader& header = aMsg.Header();
       
   205 		TInt hdid = header.ID();
       
   206 		LOG(Log::Printf(_L("\t \n --- Transaction Id:[%d]"),hdid));
       
   207 		header.SetId(hdr_id);
       
   208 		TUint16 qtype = aElement.iDnsQType;
       
   209 		if(qtype==EDnsType_A)
       
   210 			iAntype++;
       
   211 		}
       
   212 	hdr.SetAnCount(iAntype);
       
   213 	
       
   214 	hdr.SetNsCount(0);
       
   215 	}
       
   216 	
       
   217 void CDnsProxyMessageProcessor::GetAnRecordSet(TMsgBuf& aQMsg,TDnsProxydbElement& aElement)
       
   218 /**
       
   219  * Constructs answer resource record/s and appends it to buffer
       
   220  * @param -  aQMsg, dns query message
       
   221  * @param -  aElement, reference to TDnsProxydbElement class
       
   222  * @leave - system wide errors, buffer overflow
       
   223  * @internalTechnology
       
   224  **/	
       
   225 	{
       
   226 	CDnsProxyEngine& engine = iListener.GetDnsProxyEngine();
       
   227 			
       
   228 	aQMsg.Header();
       
   229 	
       
   230 	TInetAddr address = aElement.iHostAddr;
       
   231 
       
   232 	THostName name;
       
   233 	aQMsg.GetName(sizeof(aQMsg.Header()),name);	
       
   234 	
       
   235 	
       
   236 	TDndQuestion question;
       
   237 	TInt index = question.Create(aQMsg,sizeof(aQMsg.Header()));
       
   238 
       
   239 	TInt len = aQMsg.Length();
       
   240 
       
   241 	TDndRROut rrout(aQMsg);
       
   242 	
       
   243 	TDnsProxyConfigParams iEngineConfig = iListener.GetDnsProxyEngine().GetConfig();
       
   244 	rrout.iType = (TUint16)question.QType();
       
   245 	rrout.iClass = (TUint16)question.QClass();
       
   246 	rrout.iTTL = iEngineConfig.iTTL;
       
   247 	TInt ret = rrout.Append(KNullDesC8, sizeof(TDndHeader));
       
   248 	iAntype++;
       
   249 	rrout.AppendRData(address);
       
   250 	
       
   251 	engine.iDnsproxydb->AddRRecord(aElement,aQMsg,question.QType());			
       
   252 
       
   253 	}
       
   254 	
       
   255 void CDnsProxyMessageProcessor::GetNsRecordSetL(TMsgBuf& aMsg)
       
   256 /**
       
   257  * constructs and appends the authoritive resource records
       
   258  * @param -  aQMsg, dns query message
       
   259  * @leave - system wide errors, buffer overflow
       
   260  *
       
   261  * @internalTechnology
       
   262  **/
       
   263 	{
       
   264 	TDnsProxyNsRecord nsrecord;
       
   265 	TBuf8<KDnsMaxMessage> record;
       
   266 
       
   267 	//read from TTL from config
       
   268 	CDnsProxyEngine& engine = iListener.GetDnsProxyEngine();
       
   269 	TUint ttl =  engine.GetConfig().iTTL;
       
   270 	//Create RBuf
       
   271 	RBuf8 qname;
       
   272 	
       
   273 	TInt offset = sizeof(TDndHeader);
       
   274 	const TUint8* ptr = (aMsg.Ptr() + offset);
       
   275 	TPtrC8 ptrc8(aMsg.Ptr() + offset, aMsg.Size() - offset);
       
   276 	
       
   277 	qname.Create(ptrc8.Size());
       
   278 	CleanupClosePushL(qname);
       
   279 	
       
   280 	qname.Copy(TPtrC8(&ptr[0],ptrc8.Size()));
       
   281 	
       
   282 	nsrecord.ResetBuffer();
       
   283 	nsrecord.iQType = EDnsType_SOA;
       
   284 	nsrecord.iCType = EDnsClass_IN;
       
   285 	nsrecord.iTTL = ttl;
       
   286 	nsrecord.iSerialNum 	= engine.iConfigParams.iSerialNum;
       
   287 	nsrecord.iRefreshTime	= engine.iConfigParams.iRefreshTime;
       
   288 	nsrecord.iRetryTime		= engine.iConfigParams.iRetryTime;
       
   289 	nsrecord.iExpiretime	= engine.iConfigParams.iExpiretime;
       
   290 	
       
   291 	record = nsrecord.CreateNSResourceRecord(qname);
       
   292 	aMsg.Append(record);
       
   293 	CleanupStack::PopAndDestroy(&qname);
       
   294 	}
       
   295 	
       
   296 TInt CDnsProxyMessageProcessor::GetQNameSuffixL(TMsgBuf& aMsg)
       
   297 /**
       
   298  * This function gets the suffix of recieved query
       
   299  * @param aMsg - reference to dns query message
       
   300  * @return ret_val - represents whether query is local or global query
       
   301  *
       
   302  * @internalTechnology
       
   303  **/
       
   304 	{
       
   305     CDnsProxyEngine& engine = iListener.GetDnsProxyEngine();
       
   306    	
       
   307 	TInt retVal = KGlobalQuery;
       
   308 	
       
   309 	/*In case suffix information is not available
       
   310 	  treat it as global query no need of comparison*/
       
   311 	if(!engine.IsSuffixAvailable())
       
   312 	    return retVal;
       
   313 	TDndQuestion qDns;
       
   314 	qDns.Create(aMsg, sizeof(TDndHeader));
       
   315 	EDnsQType iQType = qDns.QType();
       
   316     
       
   317 	switch (qDns.QType()) 
       
   318 		{
       
   319 		case EDnsQType_A:
       
   320 			{
       
   321 			TBuf<KMaxName> buf;
       
   322 			buf.Copy(engine.iSuffixInfo);
       
   323 			HBufC8* nsuffix = CnvUtfConverter::ConvertFromUnicodeToUtf8L(buf);
       
   324 			CleanupStack::PushL(nsuffix);	
       
   325 			TPtrC8 qsuffix = nsuffix->Right(nsuffix->Length());
       
   326 			TBuf<KDnsMaxName> queryName;
       
   327 			TInt err = qDns.GetName(queryName);
       
   328 			if(err == KErrNone)
       
   329 				{
       
   330 				HBufC8* new_name = CnvUtfConverter::ConvertFromUnicodeToUtf8L(queryName);
       
   331 				TPtrC8 qname = new_name->Right(new_name->Length());
       
   332 				if(qname.Length() > qsuffix.Length())
       
   333 					{
       
   334 					TPtrC8 suffix = qname.Mid((qname.Length())-(qsuffix.Length()),qsuffix.Length());
       
   335 					TInt errVal = suffix.Compare(qsuffix);
       
   336 					if(errVal==KErrNone)
       
   337 						{
       
   338 						retVal = KLocalQuery;
       
   339 						__LOG("Processing Local Query-Type-A");
       
   340 						}
       
   341 					else
       
   342 						__LOG("Processing Global Query-Type-A");	
       
   343 					}
       
   344 		        		
       
   345 				delete new_name;
       
   346 				}
       
   347 			CleanupStack::PopAndDestroy(nsuffix);	
       
   348 			}
       
   349 			break;
       
   350 		case EDnsQType_PTR:
       
   351 			{
       
   352 			TDnsProxydbElement* element = NULL;			
       
   353 			element = LookupPTRInDb(aMsg);
       
   354 			if(element)
       
   355 				{
       
   356 				retVal = KLocalQuery;
       
   357 				}
       
   358 			else 
       
   359 				{
       
   360 				retVal = KGlobalQuery;
       
   361 				}
       
   362 			}
       
   363 			break;
       
   364 		default:
       
   365 			{
       
   366 			retVal = KGlobalQuery;
       
   367 			}
       
   368 				
       
   369 		} // end switch
       
   370 	return retVal;
       
   371 	}
       
   372 TDnsProxydbElement* CDnsProxyMessageProcessor::LookupPTRInDb(TMsgBuf& aMsg)
       
   373 /**
       
   374 * Looksup in db for existance of the recod. If present then process query as local
       
   375 * otherwise treats PTR query as a global one
       
   376 * @param aMsg - Query Message
       
   377 * @return TDnsProxydbElement - pointer to TDnsProxydbElement object
       
   378 *
       
   379 **/
       
   380 	{
       
   381 	CDnsProxyEngine& engine = iListener.GetDnsProxyEngine();
       
   382 	
       
   383 	TBuf<KPTRSufix>ptrbuf;
       
   384 	ptrbuf.Copy(KPTRSUFFIX);
       
   385 	
       
   386 	TDndQuestion qDns;
       
   387 	qDns.Create(aMsg, sizeof(TDndHeader));
       
   388 	
       
   389 	TBuf<KDnsMaxName> queryName;
       
   390 	TInt flag = qDns.GetName(queryName);
       
   391 	
       
   392 	TDnsProxydbElement* element = NULL;
       
   393 	if(queryName.Length()>ptrbuf.Length())
       
   394 		{
       
   395 		TPtrC16 ipaddr = queryName.Mid(0,(queryName.Length()-(ptrbuf.Length()+1)));
       
   396 		TInetAddr address;
       
   397 		address.Input(ipaddr);
       
   398 		TUint32 ad = address.Address();
       
   399 		TUint32 swapaddr =(((ad&0x000000FF)<<24)+((ad&0x0000FF00)<<8)+
       
   400 	   					  ((ad&0x00FF0000)>>8)+((ad&0xFF000000)>>24));
       
   401 		TInetAddr inetaddr;
       
   402 		inetaddr.SetAddress(swapaddr);
       
   403 	
       
   404 		element = engine.iDnsproxydb->FindIpAddress(inetaddr);
       
   405 		}
       
   406 					
       
   407 	return element;
       
   408 	}
       
   409 void CDnsProxyMessageProcessor::GetPTRRecord(TMsgBuf& aMsg,const TDesC8& aName)
       
   410 /**
       
   411 * Constructs PTR record and appends to TMsgBuf
       
   412 * @param aMsg - Query Message
       
   413 * @param aElement - reference to TDnsProxydbElement class which matched to query name
       
   414 *
       
   415 * @internalTechnology
       
   416 **/
       
   417 	{
       
   418 	TDndHeader &hdr = aMsg.Header();
       
   419 	
       
   420 	SetQHeaderBits(hdr);
       
   421 	hdr.SetAA(1);
       
   422 	hdr.SetAnCount(1);
       
   423 	
       
   424 	TDndQuestion question;
       
   425 	TInt index = question.Create(aMsg,sizeof(TDndHeader));
       
   426 
       
   427 	TInt len = aMsg.Length();
       
   428 
       
   429 	TDndRROut rrout(aMsg);
       
   430 	
       
   431 	rrout.iType = (TUint16)question.QType();
       
   432 	rrout.iClass = (TUint16)question.QClass();
       
   433 	
       
   434 	rrout.iTTL = iListener.GetDnsProxyEngine().GetConfig().iTTL;
       
   435 	TInt ret = rrout.Append(KNullDesC8, sizeof(TDndHeader));
       
   436 	
       
   437 	TInt err = rrout.AppendRData(aName,0);
       
   438 	}
       
   439 TDesC8& TDnsProxyNsRecord::CreateNSResourceRecord(const TDesC8& aMsg)
       
   440 /**
       
   441  * Creates new authorative answer record for given query. This will be 
       
   442  * generated when ther is no matching name found in db
       
   443  * @param aMsg - Dns query 
       
   444  * @return iNSBuf - buffer having constructed authorative answer record
       
   445  *
       
   446  * @internalTechnology
       
   447  **/	
       
   448 	{
       
   449 	
       
   450 	TInt offset_pos = aMsg.Locate(0);
       
   451 	const TUint8* ptr8 = (aMsg.Ptr());
       
   452 	TBufC8<KDnsMaxMessage> abuf_ns = TPtrC8(&ptr8[0],offset_pos);
       
   453 	
       
   454 	iNSBuf.Append(abuf_ns);
       
   455 	//this will identify the termination of the QName
       
   456 	iNSBuf.Append((TChar)0);
       
   457 
       
   458 	iNSBuf.Append(iQType/0x100);
       
   459 	iNSBuf.Append(iQType%0x100);
       
   460 	
       
   461 	iNSBuf.Append(iCType/0x100);
       
   462 	iNSBuf.Append(iCType%0x100);
       
   463 	AppendTTLBuf();
       
   464 	AppendRRLength(aMsg);
       
   465 
       
   466 	return iNSBuf;
       
   467 	}
       
   468 	
       
   469 void TDnsProxyNsRecord::AppendTTLBuf()
       
   470 /**
       
   471  * Appends the TTL to ns record set
       
   472  *
       
   473  * @internalTechnology
       
   474  **/
       
   475 	{
       
   476 	iNSBuf.Append((TChar)(iTTL / 0x1000000));
       
   477 	iNSBuf.Append((TChar)((iTTL / 0x10000) % 0x100));
       
   478 	iNSBuf.Append((TChar)((iTTL / 0x100) % 0x100));
       
   479 	iNSBuf.Append((TChar)(iTTL % 0x100));
       
   480 	}
       
   481 	
       
   482 void TDnsProxyNsRecord::AppendRRLength(const TDesC8& aMsg)
       
   483 /**
       
   484  * This function creates the NS Resource Record as specified in
       
   485  * the RFC1035 section 3.3.13.-SOA RDATA Format
       
   486  * @param - aMsg ,reference to buf which will have ns record set
       
   487  *
       
   488  * @internalTechnology
       
   489  **/
       
   490 	{
       
   491 	TBuf8<KDnsMaxMessage> buf;
       
   492 	buf.Append(aMsg);
       
   493 	buf.Append((TChar)0);
       
   494 	buf.Append(aMsg);
       
   495 	buf.Append((TChar)0);
       
   496 	
       
   497 	buf.Append((TChar)(iSerialNum / 0x1000000));
       
   498 	buf.Append((TChar)((iSerialNum / 0x10000) % 0x100));
       
   499 	buf.Append((TChar)((iSerialNum / 0x100) % 0x100));
       
   500 	buf.Append((TChar)(iSerialNum % 0x100));
       
   501 
       
   502 	buf.Append((TChar)(iRefreshTime / 0x1000000));
       
   503 	buf.Append((TChar)((iRefreshTime / 0x10000) % 0x100));
       
   504 	buf.Append((TChar)((iRefreshTime / 0x100) % 0x100));
       
   505 	buf.Append((TChar)(iRefreshTime % 0x100));
       
   506 
       
   507 	buf.Append((TChar)(iRetryTime / 0x1000000));
       
   508 	buf.Append((TChar)((iRetryTime / 0x10000) % 0x100));
       
   509 	buf.Append((TChar)((iRetryTime / 0x100) % 0x100));
       
   510 	buf.Append((TChar)(iRetryTime % 0x100));
       
   511 
       
   512 	buf.Append((TChar)(iExpiretime / 0x1000000));
       
   513 	buf.Append((TChar)((iExpiretime / 0x10000) % 0x100));
       
   514 	buf.Append((TChar)((iExpiretime / 0x100) % 0x100));
       
   515 	buf.Append((TChar)(iExpiretime % 0x100));
       
   516 
       
   517 	buf.Append((TChar)(iTTL / 0x1000000));
       
   518 	buf.Append((TChar)((iTTL / 0x10000) % 0x100));
       
   519 	buf.Append((TChar)((iTTL / 0x100) % 0x100));
       
   520 	buf.Append((TChar)(iTTL % 0x100));
       
   521 
       
   522 	TInt len = buf.Size();
       
   523 	iNSBuf.Append((TChar)(len/0x0100));
       
   524 	iNSBuf.Append((TChar)(len%0x0100));
       
   525 	
       
   526 	iNSBuf.Append(buf);
       
   527 
       
   528 	}
       
   529 
       
   530 void TDnsProxyNsRecord::ResetBuffer()
       
   531 /**
       
   532  * before appending anything newly, deletes its contents first then append
       
   533  *
       
   534  * @internalTechnology
       
   535  **/
       
   536 	{
       
   537 	TInt len = iNSBuf.Length();
       
   538 	if(len>0)
       
   539 		iNSBuf.Delete(0,len);
       
   540 	}