|
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 } |