Branch data Line data Source code
1 : : // $Id: DNS.cc 6885 2009-08-20 04:37:55Z vern $
2 : : //
3 : : // See the file "COPYING" in the main distribution directory for copyright.
4 : :
5 : : #include "config.h"
6 : :
7 : : #include <ctype.h>
8 : : #include <sys/types.h>
9 : : #include <sys/socket.h>
10 : : #include <arpa/inet.h>
11 : :
12 : : #include "NetVar.h"
13 : : #include "DNS.h"
14 : : #include "Sessions.h"
15 : : #include "Event.h"
16 : : #include "DNS_Rewriter.h"
17 : : #include "TCP_Rewriter.h"
18 : :
19 : 0 : DNS_Interpreter::DNS_Interpreter(Analyzer* arg_analyzer)
20 : : {
21 : 0 : analyzer = arg_analyzer;
22 : 0 : }
23 : :
24 : 0 : int DNS_Interpreter::ParseMessage(const u_char* data, int len, int is_query)
25 : : {
26 : 0 : int hdr_len = sizeof(DNS_RawMsgHdr);
27 : :
28 [ # # ]: 0 : if ( len < hdr_len )
29 : : {
30 : 0 : analyzer->Weird("DNS_truncated_len_lt_hdr_len");
31 : 0 : return 0;
32 : : }
33 : :
34 : 0 : DNS_MsgInfo msg((DNS_RawMsgHdr*) data, is_query);
35 : :
36 [ # # ]: 0 : if ( dns_message )
37 : : {
38 : 0 : val_list* vl = new val_list();
39 : 0 : vl->append(analyzer->BuildConnVal());
40 : 0 : vl->append(new Val(is_query, TYPE_BOOL));
41 : 0 : vl->append(msg.BuildHdrVal());
42 : 0 : vl->append(new Val(len, TYPE_COUNT));
43 : :
44 : 0 : analyzer->ConnectionEvent(dns_message, vl);
45 : : }
46 : :
47 : : // There is a great deal of non-DNS traffic that runs on port 53.
48 : : // This should weed out most of it.
49 [ # # ][ # # ]: 0 : if ( dns_max_queries > 0 && msg.qdcount > dns_max_queries )
50 : : {
51 : 0 : analyzer->Weird("DNS_Conn_count_too_large");
52 : 0 : EndMessage(&msg);
53 : 0 : return 0;
54 : : }
55 : :
56 : 0 : const u_char* msg_start = data; // needed for interpreting compression
57 : :
58 : 0 : data += hdr_len;
59 : 0 : len -= hdr_len;
60 : :
61 [ # # ]: 0 : if ( ! ParseQuestions(&msg, data, len, msg_start) )
62 : : {
63 : 0 : EndMessage(&msg);
64 : 0 : return 0;
65 : : }
66 : :
67 [ # # ]: 0 : if ( ! ParseAnswers(&msg, msg.ancount, DNS_ANSWER,
68 : : data, len, msg_start) )
69 : : {
70 : 0 : EndMessage(&msg);
71 : 0 : return 0;
72 : : }
73 : :
74 : 0 : AddrVal server(analyzer->Conn()->RespAddr());
75 : :
76 : 0 : int skip_auth = dns_skip_all_auth;
77 : 0 : int skip_addl = dns_skip_all_addl;
78 [ # # ]: 0 : if ( msg.ancount > 0 )
79 : : { // We did an answer, so can potentially skip auth/addl.
80 : : skip_auth = skip_auth || msg.nscount == 0 ||
81 [ # # ][ # # ]: 0 : dns_skip_auth->Lookup(&server);
[ # # ]
82 : : skip_addl = skip_addl || msg.arcount == 0 ||
83 [ # # ][ # # ]: 0 : dns_skip_addl->Lookup(&server);
[ # # ]
84 : : }
85 : :
86 [ # # ][ # # ]: 0 : if ( skip_auth && skip_addl )
87 : : {
88 : : // No point doing further work parsing the message.
89 : 0 : EndMessage(&msg);
90 : 0 : return 1;
91 : : }
92 : :
93 : 0 : msg.skip_event = skip_auth;
94 [ # # ]: 0 : if ( ! ParseAnswers(&msg, msg.nscount, DNS_AUTHORITY,
95 : : data, len, msg_start) )
96 : : {
97 : 0 : EndMessage(&msg);
98 : 0 : return 0;
99 : : }
100 : :
101 [ # # ]: 0 : if ( skip_addl )
102 : : {
103 : : // No point doing further work parsing the message.
104 : 0 : EndMessage(&msg);
105 : 0 : return 1;
106 : : }
107 : :
108 : 0 : msg.skip_event = skip_addl;
109 [ # # ]: 0 : if ( ! ParseAnswers(&msg, msg.arcount, DNS_ADDITIONAL,
110 : : data, len, msg_start) )
111 : : {
112 : 0 : EndMessage(&msg);
113 : 0 : return 0;
114 : : }
115 : :
116 : 0 : EndMessage(&msg);
117 : 0 : return 1;
118 : : }
119 : :
120 : 0 : int DNS_Interpreter::EndMessage(DNS_MsgInfo* msg)
121 : : {
122 : 0 : val_list* vl = new val_list;
123 : :
124 : 0 : vl->append(analyzer->BuildConnVal());
125 : 0 : vl->append(msg->BuildHdrVal());
126 : 0 : analyzer->ConnectionEvent(dns_end, vl);
127 : :
128 : 0 : return 1;
129 : : }
130 : :
131 : : int DNS_Interpreter::ParseQuestions(DNS_MsgInfo* msg,
132 : : const u_char*& data, int& len,
133 : 0 : const u_char* msg_start)
134 : : {
135 : 0 : int n = msg->qdcount;
136 : :
137 [ # # ]: 0 : if ( n == 0 )
138 : : {
139 : : // Generate event here because we won't go into ParseQuestion.
140 : : EventHandlerPtr dns_event =
141 : : msg->rcode == DNS_CODE_OK ?
142 [ # # ]: 0 : dns_query_reply : dns_rejected;
143 : 0 : BroString* question_name = new BroString("<no query>");
144 : :
145 : 0 : SendReplyOrRejectEvent(msg, dns_event, data, len, question_name);
146 : 0 : return 1;
147 : : }
148 : :
149 [ # # ][ # # ]: 0 : while ( n > 0 && ParseQuestion(msg, data, len, msg_start) )
[ # # ]
150 : 0 : --n;
151 : 0 : return n == 0;
152 : : }
153 : :
154 : : int DNS_Interpreter::ParseAnswers(DNS_MsgInfo* msg, int n, DNS_AnswerType atype,
155 : : const u_char*& data, int& len,
156 : 0 : const u_char* msg_start)
157 : : {
158 : 0 : msg->answer_type = atype;
159 : :
160 [ # # ][ # # ]: 0 : while ( n > 0 && ParseAnswer(msg, data, len, msg_start) )
[ # # ]
161 : 0 : --n;
162 : :
163 : 0 : return n == 0;
164 : : }
165 : :
166 : : int DNS_Interpreter::ParseQuestion(DNS_MsgInfo* msg,
167 : : const u_char*& data, int& len,
168 : 0 : const u_char* msg_start)
169 : : {
170 : : u_char name[513];
171 : 0 : int name_len = sizeof(name) - 1;
172 : :
173 : 0 : u_char* name_end = ExtractName(data, len, name, name_len, msg_start);
174 [ # # ]: 0 : if ( ! name_end )
175 : 0 : return 0;
176 : :
177 [ # # ]: 0 : if ( len < int(sizeof(short)) * 2 )
178 : : {
179 : 0 : analyzer->Weird("DNS_truncated_quest_too_short");
180 : 0 : return 0;
181 : : }
182 : :
183 : 0 : EventHandlerPtr dns_event = 0;
184 : :
185 [ # # ]: 0 : if ( msg->QR == 0 )
186 : 0 : dns_event = dns_request;
187 : :
188 [ # # ][ # # ]: 0 : else if ( msg->QR == 1 &&
[ # # ][ # # ]
189 : : msg->ancount == 0 && msg->nscount == 0 && msg->arcount == 0 )
190 : : // Service rejected in some fashion, and it won't be reported
191 : : // via a returned RR because there aren't any.
192 : 0 : dns_event = dns_rejected;
193 : : else
194 : 0 : dns_event = dns_query_reply;
195 : :
196 [ # # ][ # # ]: 0 : if ( dns_event && ! msg->skip_event )
[ # # ]
197 : : {
198 : : BroString* question_name =
199 : 0 : new BroString(name, name_end - name, 1);
200 : 0 : SendReplyOrRejectEvent(msg, dns_event, data, len, question_name);
201 : : }
202 : : else
203 : : {
204 : : // Consume the unused type/class.
205 : 0 : (void) ExtractShort(data, len);
206 : 0 : (void) ExtractShort(data, len);
207 : : }
208 : :
209 : 0 : return 1;
210 : : }
211 : :
212 : : int DNS_Interpreter::ParseAnswer(DNS_MsgInfo* msg,
213 : : const u_char*& data, int& len,
214 : 0 : const u_char* msg_start)
215 : : {
216 : : u_char name[513];
217 : 0 : int name_len = sizeof(name) - 1;
218 : :
219 : 0 : u_char* name_end = ExtractName(data, len, name, name_len, msg_start);
220 [ # # ]: 0 : if ( ! name_end )
221 : 0 : return 0;
222 : :
223 [ # # ]: 0 : if ( len < int(sizeof(short)) * 2 )
224 : : {
225 : 0 : analyzer->Weird("DNS_truncated_ans_too_short");
226 : 0 : return 0;
227 : : }
228 : :
229 : : // Note that the exact meaning of some of these fields will be
230 : : // re-interpreted by other, more adventurous RR types.
231 : :
232 : 0 : Unref(msg->query_name);
233 : 0 : msg->query_name = new StringVal(new BroString(name, name_end - name, 1));
234 : 0 : msg->atype = RR_Type(ExtractShort(data, len));
235 : 0 : msg->aclass = ExtractShort(data, len);
236 : 0 : msg->ttl = ExtractLong(data, len);
237 : :
238 : 0 : int rdlength = ExtractShort(data, len);
239 [ # # ]: 0 : if ( rdlength > len )
240 : : {
241 : 0 : analyzer->Weird("DNS_truncated_RR_rdlength_lt_len");
242 : 0 : return 0;
243 : : }
244 : :
245 : : int status;
246 [ # # # # # : 0 : switch ( msg->atype ) {
# # # # #
# # # ]
247 : : case TYPE_A:
248 : 0 : status = ParseRR_A(msg, data, len, rdlength);
249 : 0 : break;
250 : :
251 : : case TYPE_A6:
252 : : case TYPE_AAAA:
253 : 0 : status = ParseRR_AAAA(msg, data, len, rdlength);
254 : 0 : break;
255 : :
256 : : case TYPE_NS:
257 : : case TYPE_CNAME:
258 : : case TYPE_PTR:
259 : 0 : status = ParseRR_Name(msg, data, len, rdlength, msg_start);
260 : 0 : break;
261 : :
262 : : case TYPE_SOA:
263 : 0 : status = ParseRR_SOA(msg, data, len, rdlength, msg_start);
264 : 0 : break;
265 : :
266 : : case TYPE_WKS:
267 : 0 : status = ParseRR_WKS(msg, data, len, rdlength);
268 : 0 : break;
269 : :
270 : : case TYPE_HINFO:
271 : 0 : status = ParseRR_HINFO(msg, data, len, rdlength);
272 : 0 : break;
273 : :
274 : : case TYPE_MX:
275 : 0 : status = ParseRR_MX(msg, data, len, rdlength, msg_start);
276 : 0 : break;
277 : :
278 : : case TYPE_TXT:
279 : 0 : status = ParseRR_TXT(msg, data, len, rdlength, msg_start);
280 : 0 : break;
281 : :
282 : : case TYPE_NBS:
283 : 0 : status = ParseRR_NBS(msg, data, len, rdlength, msg_start);
284 : 0 : break;
285 : :
286 : : case TYPE_SRV:
287 : 0 : status = ParseRR_SRV(msg, data, len, rdlength, msg_start);
288 : 0 : break;
289 : :
290 : : case TYPE_EDNS:
291 : 0 : status = ParseRR_EDNS(msg, data, len, rdlength, msg_start);
292 : 0 : break;
293 : :
294 : : case TYPE_TSIG:
295 : 0 : status = ParseRR_TSIG(msg, data, len, rdlength, msg_start);
296 : 0 : break;
297 : :
298 : : default:
299 : 0 : analyzer->Weird("DNS_RR_unknown_type");
300 : 0 : data += rdlength;
301 : 0 : len -= rdlength;
302 : 0 : status = 1;
303 : : break;
304 : : }
305 : :
306 : 0 : return status;
307 : : }
308 : :
309 : : u_char* DNS_Interpreter::ExtractName(const u_char*& data, int& len,
310 : : u_char* name, int name_len,
311 : 0 : const u_char* msg_start)
312 : : {
313 : 0 : u_char* name_start = name;
314 : :
315 [ # # ]: 0 : while ( ExtractLabel(data, len, name, name_len, msg_start) )
316 : : ;
317 : :
318 : 0 : int n = name - name_start;
319 : :
320 [ # # ]: 0 : if ( n >= 255 )
321 : 0 : analyzer->Weird("DNS_NAME_too_long");
322 : :
323 [ # # ][ # # ]: 0 : if ( n >= 2 && name[-1] == '.' )
324 : : {
325 : : // Remove trailing dot.
326 : 0 : --name;
327 : 0 : name[0] = 0;
328 : : }
329 : :
330 : : // Convert labels to lower case for consistency.
331 [ # # ]: 0 : for ( u_char* np = name_start; np < name; ++np )
332 [ # # ]: 0 : if ( isupper(*np) )
333 : 0 : *np = tolower(*np);
334 : :
335 : 0 : return name;
336 : : }
337 : :
338 : : int DNS_Interpreter::ExtractLabel(const u_char*& data, int& len,
339 : : u_char*& name, int& name_len,
340 : 0 : const u_char* msg_start)
341 : : {
342 [ # # ]: 0 : if ( len <= 0 )
343 : 0 : return 0;
344 : :
345 : 0 : const u_char* orig_data = data;
346 : 0 : int label_len = data[0];
347 : :
348 : 0 : ++data;
349 : 0 : --len;
350 : :
351 [ # # ]: 0 : if ( len <= 0 )
352 : 0 : return 0;
353 : :
354 [ # # ]: 0 : if ( label_len == 0 )
355 : : // Found terminating label.
356 : 0 : return 0;
357 : :
358 [ # # ]: 0 : if ( (label_len & 0xc0) == 0xc0 )
359 : : {
360 : 0 : unsigned short offset = (label_len & ~0xc0) << 8;
361 : :
362 : 0 : offset |= *data;
363 : :
364 : 0 : ++data;
365 : 0 : --len;
366 : :
367 [ # # ]: 0 : if ( offset >= orig_data - msg_start )
368 : : {
369 : : // (You'd think that actually the offset should be
370 : : // at least 6 bytes below our current position:
371 : : // 2 bytes for a non-trivial label, plus 4 bytes for
372 : : // its class and type, which presumably are between
373 : : // our current location and the instance of the label.
374 : : // But actually this turns out not to be the case -
375 : : // sometimes compression points to compression.)
376 : :
377 : 0 : analyzer->Weird("DNS_label_forward_compress_offset");
378 : 0 : return 0;
379 : : }
380 : :
381 : : // Recursively resolve name.
382 : 0 : const u_char* recurse_data = msg_start + offset;
383 : 0 : int recurse_max_len = orig_data - recurse_data;
384 : :
385 : : u_char* name_end = ExtractName(recurse_data, recurse_max_len,
386 : 0 : name, name_len, msg_start);
387 : :
388 : 0 : name_len -= name_end - name;
389 : 0 : name = name_end;
390 : :
391 : 0 : return 0;
392 : : }
393 : :
394 [ # # ]: 0 : if ( label_len > len )
395 : : {
396 : 0 : analyzer->Weird("DNS_label_len_gt_pkt");
397 : 0 : data += len; // consume the rest of the packet
398 : 0 : len = 0;
399 : 0 : return 0;
400 : : }
401 : :
402 [ # # ]: 0 : if ( label_len > 63 )
403 : : {
404 : 0 : analyzer->Weird("DNS_label_too_long");
405 : 0 : return 0;
406 : : }
407 : :
408 [ # # ]: 0 : if ( label_len >= name_len )
409 : : {
410 : 0 : analyzer->Weird("DNS_label_len_gt_name_len");
411 : 0 : return 0;
412 : : }
413 : :
414 : 0 : memcpy(name, data, label_len);
415 : 0 : name[label_len] = '.';
416 : :
417 : 0 : name += label_len + 1;
418 : 0 : name_len -= label_len + 1;
419 : :
420 : 0 : data += label_len;
421 : 0 : len -= label_len;
422 : :
423 : 0 : return 1;
424 : : }
425 : :
426 : 0 : uint16 DNS_Interpreter::ExtractShort(const u_char*& data, int& len)
427 : : {
428 [ # # ]: 0 : if ( len < 2 )
429 : 0 : return 0;
430 : :
431 : : uint16 val;
432 : :
433 : 0 : val = data[0] << 8;
434 : :
435 : 0 : ++data;
436 : 0 : --len;
437 : :
438 : 0 : val |= data[0];
439 : :
440 : 0 : ++data;
441 : 0 : --len;
442 : :
443 : 0 : return val;
444 : : }
445 : :
446 : 0 : uint32 DNS_Interpreter::ExtractLong(const u_char*& data, int& len)
447 : : {
448 [ # # ]: 0 : if ( len < 4 )
449 : 0 : return 0;
450 : :
451 : : uint32 val;
452 : :
453 : 0 : val = data[0] << 24;
454 : 0 : val |= data[1] << 16;
455 : 0 : val |= data[2] << 8;
456 : 0 : val |= data[3];
457 : :
458 : 0 : data += sizeof(val);
459 : 0 : len -= sizeof(val);
460 : :
461 : 0 : return val;
462 : : }
463 : :
464 : : int DNS_Interpreter::ParseRR_Name(DNS_MsgInfo* msg,
465 : : const u_char*& data, int& len, int rdlength,
466 : 0 : const u_char* msg_start)
467 : : {
468 : 0 : const u_char* data_start = data;
469 : :
470 : : u_char name[513];
471 : 0 : int name_len = sizeof(name) - 1;
472 : :
473 : 0 : u_char* name_end = ExtractName(data, len, name, name_len, msg_start);
474 [ # # ]: 0 : if ( ! name_end )
475 : 0 : return 0;
476 : :
477 [ # # ]: 0 : if ( data - data_start != rdlength )
478 : : {
479 : 0 : analyzer->Weird("DNS_RR_length_mismatch");
480 : : }
481 : :
482 : 0 : EventHandlerPtr reply_event;
483 [ # # # # ]: 0 : switch ( msg->atype ) {
484 : : case TYPE_NS:
485 : 0 : reply_event = dns_NS_reply;
486 : 0 : break;
487 : :
488 : : case TYPE_CNAME:
489 : : case TYPE_AAAA:
490 : : case TYPE_A6:
491 : 0 : reply_event = dns_CNAME_reply;
492 : 0 : break;
493 : :
494 : : case TYPE_PTR:
495 : 0 : reply_event = dns_PTR_reply;
496 : 0 : break;
497 : :
498 : : default:
499 : 0 : analyzer->Conn()->Internal("DNS_RR_bad_name");
500 : 0 : reply_event = 0;
501 : : }
502 : :
503 [ # # ][ # # ]: 0 : if ( reply_event && ! msg->skip_event )
[ # # ]
504 : : {
505 : 0 : val_list* vl = new val_list;
506 : :
507 : 0 : vl->append(analyzer->BuildConnVal());
508 : 0 : vl->append(msg->BuildHdrVal());
509 : 0 : vl->append(msg->BuildAnswerVal());
510 : 0 : vl->append(new StringVal(new BroString(name, name_end - name, 1)));
511 : :
512 : 0 : analyzer->ConnectionEvent(reply_event, vl);
513 : : }
514 : :
515 : 0 : return 1;
516 : : }
517 : :
518 : : int DNS_Interpreter::ParseRR_SOA(DNS_MsgInfo* msg,
519 : : const u_char*& data, int& len, int rdlength,
520 : 0 : const u_char* msg_start)
521 : : {
522 : 0 : const u_char* data_start = data;
523 : :
524 : : u_char mname[513];
525 : 0 : int mname_len = sizeof(mname) - 1;
526 : :
527 : 0 : u_char* mname_end = ExtractName(data, len, mname, mname_len, msg_start);
528 [ # # ]: 0 : if ( ! mname_end )
529 : 0 : return 0;
530 : :
531 : : u_char rname[513];
532 : 0 : int rname_len = sizeof(rname) - 1;
533 : :
534 : 0 : u_char* rname_end = ExtractName(data, len, rname, rname_len, msg_start);
535 [ # # ]: 0 : if ( ! rname_end )
536 : 0 : return 0;
537 : :
538 [ # # ]: 0 : if ( len < 20 )
539 : 0 : return 0;
540 : :
541 : 0 : uint32 serial = ExtractLong(data, len);
542 : 0 : uint32 refresh = ExtractLong(data, len);
543 : 0 : uint32 retry = ExtractLong(data, len);
544 : 0 : uint32 expire = ExtractLong(data, len);
545 : 0 : uint32 minimum = ExtractLong(data, len);
546 : :
547 [ # # ]: 0 : if ( data - data_start != rdlength )
548 : 0 : analyzer->Weird("DNS_RR_length_mismatch");
549 : :
550 [ # # ][ # # ]: 0 : if ( dns_SOA_reply && ! msg->skip_event )
[ # # ]
551 : : {
552 : 0 : val_list* vl = new val_list;
553 : :
554 : 0 : vl->append(analyzer->BuildConnVal());
555 : 0 : vl->append(msg->BuildHdrVal());
556 : 0 : vl->append(msg->BuildAnswerVal());
557 : :
558 : 0 : RecordVal* r = new RecordVal(dns_soa);
559 : :
560 : 0 : r->Assign(0, new StringVal(new BroString(mname, mname_end - mname, 1)));
561 : 0 : r->Assign(1, new StringVal(new BroString(rname, rname_end - rname, 1)));
562 : 0 : r->Assign(2, new Val(serial, TYPE_COUNT));
563 : 0 : r->Assign(3, new IntervalVal(double(refresh), Seconds));
564 : 0 : r->Assign(4, new IntervalVal(double(retry), Seconds));
565 : 0 : r->Assign(5, new IntervalVal(double(expire), Seconds));
566 : 0 : r->Assign(6, new IntervalVal(double(minimum), Seconds));
567 : :
568 : 0 : vl->append(r);
569 : :
570 : 0 : analyzer->ConnectionEvent(dns_SOA_reply, vl);
571 : : }
572 : :
573 : 0 : return 1;
574 : : }
575 : :
576 : : int DNS_Interpreter::ParseRR_MX(DNS_MsgInfo* msg,
577 : : const u_char*& data, int& len, int rdlength,
578 : 0 : const u_char* msg_start)
579 : : {
580 : 0 : const u_char* data_start = data;
581 : :
582 : 0 : int preference = ExtractShort(data, len);
583 : :
584 : : u_char name[513];
585 : 0 : int name_len = sizeof(name) - 1;
586 : :
587 : 0 : u_char* name_end = ExtractName(data, len, name, name_len, msg_start);
588 [ # # ]: 0 : if ( ! name_end )
589 : 0 : return 0;
590 : :
591 [ # # ]: 0 : if ( data - data_start != rdlength )
592 : 0 : analyzer->Weird("DNS_RR_length_mismatch");
593 : :
594 [ # # ][ # # ]: 0 : if ( dns_MX_reply && ! msg->skip_event )
[ # # ]
595 : : {
596 : 0 : val_list* vl = new val_list;
597 : :
598 : 0 : vl->append(analyzer->BuildConnVal());
599 : 0 : vl->append(msg->BuildHdrVal());
600 : 0 : vl->append(msg->BuildAnswerVal());
601 : 0 : vl->append(new StringVal(new BroString(name, name_end - name, 1)));
602 : 0 : vl->append(new Val(preference, TYPE_COUNT));
603 : :
604 : 0 : analyzer->ConnectionEvent(dns_MX_reply, vl);
605 : : }
606 : :
607 : 0 : return 1;
608 : : }
609 : :
610 : : int DNS_Interpreter::ParseRR_NBS(DNS_MsgInfo* msg,
611 : : const u_char*& data, int& len, int rdlength,
612 : 0 : const u_char* msg_start)
613 : : {
614 : 0 : data += rdlength;
615 : 0 : len -= rdlength;
616 : 0 : return 1;
617 : : }
618 : :
619 : : int DNS_Interpreter::ParseRR_SRV(DNS_MsgInfo* msg,
620 : : const u_char*& data, int& len, int rdlength,
621 : 0 : const u_char* msg_start)
622 : : {
623 : 0 : const u_char* data_start = data;
624 : :
625 : 0 : unsigned int priority = ExtractShort(data, len);
626 : 0 : unsigned int weight = ExtractShort(data, len);
627 : 0 : unsigned int port = ExtractShort(data, len);
628 : :
629 : : u_char name[513];
630 : 0 : int name_len = sizeof(name) - 1;
631 : :
632 : 0 : u_char* name_end = ExtractName(data, len, name, name_len, msg_start);
633 [ # # ]: 0 : if ( ! name_end )
634 : 0 : return 0;
635 : 0 : *name_end = 0; // terminate name so we can use it in snprintf()
636 : :
637 [ # # ]: 0 : if ( data - data_start != rdlength )
638 : 0 : analyzer->Weird("DNS_RR_length_mismatch");
639 : :
640 : : // The following is just a placeholder.
641 : : char buf[2048];
642 : : safe_snprintf(buf, sizeof(buf), "SRV %s priority=%d weight=%d port=%d",
643 : 0 : name, priority, weight, port);
644 : 0 : return 1;
645 : : }
646 : :
647 : : int DNS_Interpreter::ParseRR_EDNS(DNS_MsgInfo* msg,
648 : : const u_char*& data, int& len, int rdlength,
649 : 0 : const u_char* msg_start)
650 : : {
651 : : // We need a pair-value set mechanism here to dump useful information
652 : : // out to the policy side of the house if rdlength > 0.
653 : :
654 [ # # ][ # # ]: 0 : if ( dns_EDNS_addl && ! msg->skip_event )
[ # # ]
655 : : {
656 : 0 : val_list* vl = new val_list;
657 : :
658 : 0 : vl->append(analyzer->BuildConnVal());
659 : 0 : vl->append(msg->BuildHdrVal());
660 : 0 : vl->append(msg->BuildEDNS_Val());
661 : 0 : analyzer->ConnectionEvent(dns_EDNS_addl, vl);
662 : : }
663 : :
664 : : // Currently EDNS supports the movement of type:data pairs
665 : : // in the RR_DATA section. Here's where we should put together
666 : : // a corresponding mechanism.
667 [ # # ]: 0 : if ( rdlength > 0 )
668 : : { // deal with data
669 : 0 : data += rdlength;
670 : 0 : len -= rdlength;
671 : : }
672 : : else
673 : : { // no data, move on
674 : 0 : data += rdlength;
675 : 0 : len -= rdlength;
676 : : }
677 : :
678 : 0 : return 1;
679 : : }
680 : :
681 : : int DNS_Interpreter::ParseRR_TSIG(DNS_MsgInfo* msg,
682 : : const u_char*& data, int& len, int rdlength,
683 : 0 : const u_char* msg_start)
684 : : {
685 : 0 : const u_char* data_start = data;
686 : : u_char alg_name[1024];
687 : 0 : int alg_name_len = sizeof(alg_name) - 1;
688 : :
689 : : u_char* alg_name_end =
690 : 0 : ExtractName(data, len, alg_name, alg_name_len, msg_start);
691 : :
692 [ # # ]: 0 : if ( ! alg_name_end )
693 : 0 : return 0;
694 : :
695 : 0 : uint32 sign_time_sec = ExtractLong(data, len);
696 : 0 : unsigned int sign_time_msec = ExtractShort(data, len);
697 : 0 : unsigned int fudge = ExtractShort(data, len);
698 : :
699 : : u_char request_MAC[16];
700 : 0 : memcpy(request_MAC, data, sizeof(request_MAC));
701 : :
702 : : // Here we adjust the size of the requested MAC + u_int16_t
703 : : // for length. See RFC 2845, sec 2.3.
704 : 0 : int n = sizeof(request_MAC) + sizeof(u_int16_t);
705 : 0 : data += n;
706 : 0 : len -= n;
707 : :
708 : 0 : unsigned int orig_id = ExtractShort(data, len);
709 : 0 : unsigned int rr_error = ExtractShort(data, len);
710 : :
711 : 0 : msg->tsig = new TSIG_DATA;
712 : :
713 : : msg->tsig->alg_name =
714 : 0 : new BroString(alg_name, alg_name_end - alg_name, 1);
715 : 0 : msg->tsig->sig = new BroString(request_MAC, sizeof(request_MAC), 1);
716 : 0 : msg->tsig->time_s = sign_time_sec;
717 : 0 : msg->tsig->time_ms = sign_time_msec;
718 : 0 : msg->tsig->fudge = fudge;
719 : 0 : msg->tsig->orig_id = orig_id;
720 : 0 : msg->tsig->rr_error = rr_error;
721 : :
722 : 0 : val_list* vl = new val_list;
723 : :
724 : 0 : vl->append(analyzer->BuildConnVal());
725 : 0 : vl->append(msg->BuildHdrVal());
726 : 0 : vl->append(msg->BuildTSIG_Val());
727 : :
728 : 0 : analyzer->ConnectionEvent(dns_TSIG_addl, vl);
729 : :
730 : 0 : return 1;
731 : : }
732 : :
733 : : int DNS_Interpreter::ParseRR_A(DNS_MsgInfo* msg,
734 : 0 : const u_char*& data, int& len, int rdlength)
735 : : {
736 [ # # ]: 0 : if ( rdlength != 4 )
737 : : {
738 : 0 : analyzer->Weird("DNS_RR_bad_length");
739 : 0 : return 0;
740 : : }
741 : :
742 : 0 : uint32 addr = ExtractLong(data, len);
743 : :
744 [ # # # # ]: 0 : if ( dns_A_reply && ! msg->skip_event )
[ # # ]
745 : : {
746 : 0 : val_list* vl = new val_list;
747 : :
748 : 0 : vl->append(analyzer->BuildConnVal());
749 : 0 : vl->append(msg->BuildHdrVal());
750 : 0 : vl->append(msg->BuildAnswerVal());
751 : 0 : vl->append(new AddrVal(htonl(addr)));
752 : :
753 : 0 : analyzer->ConnectionEvent(dns_A_reply, vl);
754 : : }
755 : :
756 : 0 : return 1;
757 : : }
758 : :
759 : : int DNS_Interpreter::ParseRR_AAAA(DNS_MsgInfo* msg,
760 : 0 : const u_char*& data, int& len, int rdlength)
761 : : {
762 : : // We need to parse an IPv6 address, high-order byte first.
763 : : // ### Currently, we fake an A reply rather than an AAAA reply,
764 : : // since for the latter we won't be able to express the full
765 : : // address (unless Bro was compiled for IPv6 addresses). We do
766 : : // this fake by using just the bottom 4 bytes of the IPv6 address.
767 : : uint32 addr[4];
768 : : int i;
769 : :
770 [ # # ]: 0 : for ( i = 0; i < 4; ++i )
771 : : {
772 : 0 : addr[i] = ntohl(ExtractLong(data, len));
773 : :
774 [ # # ]: 0 : if ( len < 0 )
775 : : {
776 : 0 : analyzer->Weird("DNS_AAAA_neg_length");
777 : 0 : return 0;
778 : : }
779 : : }
780 : :
781 : : // Currently, dns_AAAA_reply is treated like dns_A_reply, since
782 : : // IPv6 addresses are not generally processed. This needs to be
783 : : // fixed. ###
784 [ # # ][ # # ]: 0 : if ( dns_A_reply && ! msg->skip_event )
[ # # ]
785 : : {
786 : 0 : val_list* vl = new val_list;
787 : :
788 : 0 : vl->append(analyzer->BuildConnVal());
789 : 0 : vl->append(msg->BuildHdrVal());
790 : 0 : vl->append(msg->BuildAnswerVal());
791 : 0 : vl->append(new AddrVal(htonl(addr[3])));
792 : :
793 : 0 : analyzer->ConnectionEvent(dns_A_reply, vl);
794 : : }
795 : :
796 : : #if 0
797 : : alternative AAAA code from Chris
798 : : if ( dns_AAAA_reply && ! msg->skip_event )
799 : : {
800 : : val_list* vl = new val_list;
801 : :
802 : : vl->append(analyzer->BuildConnVal());
803 : : vl->append(msg->BuildHdrVal());
804 : : vl->append(msg->BuildAnswerVal());
805 : : #ifdef BROv6
806 : : // FIXME: might need to htonl the addr first
807 : : vl->append(new AddrVal(addr));
808 : : #else
809 : : vl->append(new AddrVal((uint32)0x0000));
810 : : #endif
811 : : char addrstr[INET6_ADDRSTRLEN];
812 : : inet_ntop(AF_INET6, addr, addrstr, INET6_ADDRSTRLEN);
813 : : vl->append(new StringVal(addrstr));
814 : :
815 : : analyzer->ConnectionEvent(dns_AAAA_reply, vl);
816 : : }
817 : : #endif
818 : :
819 : 0 : return 1;
820 : : }
821 : :
822 : : int DNS_Interpreter::ParseRR_WKS(DNS_MsgInfo* msg,
823 : 0 : const u_char*& data, int& len, int rdlength)
824 : : {
825 : 0 : data += rdlength;
826 : 0 : len -= rdlength;
827 : :
828 : 0 : return 1;
829 : : }
830 : :
831 : : int DNS_Interpreter::ParseRR_HINFO(DNS_MsgInfo* msg,
832 : 0 : const u_char*& data, int& len, int rdlength)
833 : : {
834 : 0 : data += rdlength;
835 : 0 : len -= rdlength;
836 : :
837 : 0 : return 1;
838 : : }
839 : :
840 : : int DNS_Interpreter::ParseRR_TXT(DNS_MsgInfo* msg,
841 : : const u_char*& data, int& len, int rdlength,
842 : 0 : const u_char* msg_start)
843 : : {
844 : 0 : int name_len = data[0];
845 : :
846 : 0 : char* name = new char[name_len];
847 : :
848 : 0 : memcpy(name, data+1, name_len);
849 : :
850 : 0 : data += rdlength;
851 : 0 : len -= rdlength;
852 : :
853 [ # # # # ]: 0 : if ( dns_TXT_reply && ! msg->skip_event )
[ # # ]
854 : : {
855 : 0 : val_list* vl = new val_list;
856 : :
857 : 0 : vl->append(analyzer->BuildConnVal());
858 : 0 : vl->append(msg->BuildHdrVal());
859 : 0 : vl->append(msg->BuildAnswerVal());
860 : 0 : vl->append(new StringVal(name_len, name));
861 : :
862 : 0 : analyzer->ConnectionEvent(dns_TXT_reply, vl);
863 : : }
864 : :
865 [ # # ]: 0 : delete [] name;
866 : :
867 : 0 : return 1;
868 : : }
869 : :
870 : : void DNS_Interpreter::SendReplyOrRejectEvent(DNS_MsgInfo* msg,
871 : : EventHandlerPtr event,
872 : : const u_char*& data, int& len,
873 : 0 : BroString* question_name)
874 : : {
875 : 0 : RR_Type qtype = RR_Type(ExtractShort(data, len));
876 : 0 : int qclass = ExtractShort(data, len);
877 : :
878 : 0 : val_list* vl = new val_list;
879 : 0 : vl->append(analyzer->BuildConnVal());
880 : 0 : vl->append(msg->BuildHdrVal());
881 : 0 : vl->append(new StringVal(question_name));
882 : 0 : vl->append(new Val(qtype, TYPE_COUNT));
883 : 0 : vl->append(new Val(qclass, TYPE_COUNT));
884 : :
885 : 0 : analyzer->ConnectionEvent(event, vl);
886 : 0 : }
887 : :
888 : :
889 : 0 : DNS_MsgInfo::DNS_MsgInfo(DNS_RawMsgHdr* hdr, int arg_is_query)
890 : : {
891 : : //### Need to fix alignment if hdr is misaligned (not on a short
892 : : // boundary).
893 : 0 : unsigned short flags = ntohs(hdr->flags);
894 : :
895 : 0 : QR = (flags & 0x8000) != 0;
896 : 0 : opcode = (flags & 0x7800) >> 11;
897 : 0 : AA = (flags & 0x0400) != 0;
898 : 0 : TC = (flags & 0x0200) != 0;
899 : 0 : RD = (flags & 0x0100) != 0;
900 : 0 : RA = (flags & 0x0080) != 0;
901 : 0 : Z = (flags & 0x0070) >> 4;
902 : 0 : rcode = (flags & 0x000f);
903 : :
904 : 0 : qdcount = ntohs(hdr->qdcount);
905 : 0 : ancount = ntohs(hdr->ancount);
906 : 0 : nscount = ntohs(hdr->nscount);
907 : 0 : arcount = ntohs(hdr->arcount);
908 : :
909 : 0 : id = ntohs(hdr->id);
910 : 0 : is_query = arg_is_query;
911 : :
912 : 0 : query_name = 0;
913 : 0 : atype = TYPE_ALL;
914 : 0 : aclass = 0;
915 : 0 : ttl = 0;
916 : :
917 : 0 : answer_type = DNS_QUESTION;
918 : 0 : skip_event = 0;
919 : 0 : }
920 : :
921 : 0 : DNS_MsgInfo::~DNS_MsgInfo()
922 : : {
923 : 0 : Unref(query_name);
924 : 0 : }
925 : :
926 : 0 : Val* DNS_MsgInfo::BuildHdrVal()
927 : : {
928 : 0 : RecordVal* r = new RecordVal(dns_msg);
929 : :
930 : 0 : r->Assign(0, new Val(id, TYPE_COUNT));
931 : 0 : r->Assign(1, new Val(opcode, TYPE_COUNT));
932 : 0 : r->Assign(2, new Val(rcode, TYPE_COUNT));
933 : 0 : r->Assign(3, new Val(QR, TYPE_BOOL));
934 : 0 : r->Assign(4, new Val(AA, TYPE_BOOL));
935 : 0 : r->Assign(5, new Val(TC, TYPE_BOOL));
936 : 0 : r->Assign(6, new Val(RD, TYPE_BOOL));
937 : 0 : r->Assign(7, new Val(RA, TYPE_BOOL));
938 : 0 : r->Assign(8, new Val(Z, TYPE_COUNT));
939 : 0 : r->Assign(9, new Val(qdcount, TYPE_COUNT));
940 : 0 : r->Assign(10, new Val(ancount, TYPE_COUNT));
941 : 0 : r->Assign(11, new Val(nscount, TYPE_COUNT));
942 : 0 : r->Assign(12, new Val(arcount, TYPE_COUNT));
943 : :
944 : 0 : return r;
945 : : }
946 : :
947 : 0 : Val* DNS_MsgInfo::BuildAnswerVal()
948 : : {
949 : 0 : RecordVal* r = new RecordVal(dns_answer);
950 : :
951 : 0 : Ref(query_name);
952 : 0 : r->Assign(0, new Val(int(answer_type), TYPE_COUNT));
953 : 0 : r->Assign(1, query_name);
954 : 0 : r->Assign(2, new Val(atype, TYPE_COUNT));
955 : 0 : r->Assign(3, new Val(aclass, TYPE_COUNT));
956 : 0 : r->Assign(4, new IntervalVal(double(ttl), Seconds));
957 : :
958 : 0 : return r;
959 : : }
960 : :
961 : 0 : Val* DNS_MsgInfo::BuildEDNS_Val()
962 : : {
963 : : // We have to treat the additional record type in EDNS differently
964 : : // than a regular resource record.
965 : 0 : RecordVal* r = new RecordVal(dns_edns_additional);
966 : :
967 : 0 : Ref(query_name);
968 : 0 : r->Assign(0, new Val(int(answer_type), TYPE_COUNT));
969 : 0 : r->Assign(1, query_name);
970 : :
971 : : // type = 0x29 or 41 = EDNS
972 : 0 : r->Assign(2, new Val(atype, TYPE_COUNT));
973 : :
974 : : // sender's UDP payload size, per RFC 2671 4.3
975 : 0 : r->Assign(3, new Val(aclass, TYPE_COUNT));
976 : :
977 : : // Need to break the TTL field into three components:
978 : : // initial: [------------- ttl (32) ---------------------]
979 : : // after: [DO][ ext rcode (7)][ver # (8)][ Z field (16)]
980 : :
981 : 0 : unsigned int ercode = (ttl >> 24) & 0xff;
982 : 0 : unsigned int version = (ttl >> 16) & 0xff;
983 : : // unsigned int DO = ttl & 0x8000; // "DNSSEC OK" - RFC 3225
984 : 0 : unsigned int z = ttl & 0xffff;
985 : :
986 : 0 : unsigned int return_error = (ercode << 8) | rcode;
987 : :
988 : 0 : r->Assign(4, new Val(return_error, TYPE_COUNT));
989 : 0 : r->Assign(5, new Val(version, TYPE_COUNT));
990 : 0 : r->Assign(6, new Val(z, TYPE_COUNT));
991 : 0 : r->Assign(7, new IntervalVal(double(ttl), Seconds));
992 : 0 : r->Assign(8, new Val(is_query, TYPE_COUNT));
993 : :
994 : 0 : return r;
995 : : }
996 : :
997 : 0 : Val* DNS_MsgInfo::BuildTSIG_Val()
998 : : {
999 : 0 : RecordVal* r = new RecordVal(dns_tsig_additional);
1000 : 0 : double rtime = tsig->time_s + tsig->time_ms / 1000.0;
1001 : :
1002 : 0 : Ref(query_name);
1003 : : // r->Assign(0, new Val(int(answer_type), TYPE_COUNT));
1004 : 0 : r->Assign(0, query_name);
1005 : 0 : r->Assign(1, new Val(int(answer_type), TYPE_COUNT));
1006 : 0 : r->Assign(2, new StringVal(tsig->alg_name));
1007 : 0 : r->Assign(3, new StringVal(tsig->sig));
1008 : 0 : r->Assign(4, new Val(rtime, TYPE_TIME));
1009 : 0 : r->Assign(5, new Val(double(tsig->fudge), TYPE_TIME));
1010 : 0 : r->Assign(6, new Val(tsig->orig_id, TYPE_COUNT));
1011 : 0 : r->Assign(7, new Val(tsig->rr_error, TYPE_COUNT));
1012 : 0 : r->Assign(8, new Val(is_query, TYPE_COUNT));
1013 : :
1014 : 0 : delete tsig;
1015 : 0 : tsig = 0;
1016 : :
1017 : 0 : return r;
1018 : : }
1019 : :
1020 : : Contents_DNS::Contents_DNS(Connection* conn, bool orig,
1021 : 0 : DNS_Interpreter* arg_interp)
1022 : 0 : : TCP_SupportAnalyzer(AnalyzerTag::Contents_DNS, conn, orig)
1023 : : {
1024 : 0 : interp = arg_interp;
1025 : :
1026 : 0 : msg_buf = 0;
1027 : 0 : buf_n = msg_size = 0;
1028 : 0 : state = DNS_LEN_HI;
1029 : 0 : }
1030 : :
1031 : 0 : Contents_DNS::~Contents_DNS()
1032 : : {
1033 : 0 : delete msg_buf;
1034 [ # # ][ # # ]: 0 : }
[ # # ]
1035 : :
1036 : 0 : void Contents_DNS::Flush()
1037 : : {
1038 [ # # ]: 0 : if ( buf_n > 0 )
1039 : : { // Deliver partial message.
1040 : 0 : interp->ParseMessage(msg_buf, buf_n, true);
1041 : 0 : msg_size = 0;
1042 : : }
1043 : 0 : }
1044 : :
1045 : 0 : void Contents_DNS::DeliverStream(int len, const u_char* data, bool orig)
1046 : : {
1047 [ # # ]: 0 : if ( state == DNS_LEN_HI )
1048 : : {
1049 : 0 : msg_size = (*data) << 8;
1050 : 0 : state = DNS_LEN_LO;
1051 : :
1052 : 0 : ++data;
1053 : 0 : --len;
1054 : :
1055 [ # # ]: 0 : if ( len == 0 )
1056 : 0 : return;
1057 : : }
1058 : :
1059 [ # # ]: 0 : if ( state == DNS_LEN_LO )
1060 : : {
1061 : 0 : msg_size += *data;
1062 : 0 : state = DNS_MESSAGE_BUFFER;
1063 : :
1064 : 0 : buf_n = 0;
1065 : :
1066 [ # # ]: 0 : if ( msg_buf )
1067 : : {
1068 [ # # ]: 0 : if ( buf_len < msg_size )
1069 : : {
1070 : 0 : buf_len = msg_size;
1071 : 0 : msg_buf = (u_char*) safe_realloc((void*) msg_buf, buf_len);
1072 : : }
1073 : : }
1074 : : else
1075 : : {
1076 : 0 : buf_len = msg_size;
1077 : 0 : msg_buf = (u_char*) safe_malloc(buf_len);
1078 : : }
1079 : :
1080 : 0 : ++data;
1081 : 0 : --len;
1082 : :
1083 [ # # ]: 0 : if ( len == 0 )
1084 : 0 : return;
1085 : : }
1086 : :
1087 [ # # ]: 0 : if ( state != DNS_MESSAGE_BUFFER )
1088 : 0 : Conn()->Internal("state inconsistency in Contents_DNS::DeliverStream");
1089 : :
1090 : : int n;
1091 [ # # ][ # # ]: 0 : for ( n = 0; buf_n < msg_size && n < len; ++n )
1092 : 0 : msg_buf[buf_n++] = data[n];
1093 : :
1094 [ # # ]: 0 : if ( buf_n < msg_size )
1095 : : // Haven't filled up the message buffer yet, no more to do.
1096 : 0 : return;
1097 : :
1098 : 0 : ForwardPacket(msg_size, msg_buf, orig, -1, 0, 0);
1099 : :
1100 : 0 : buf_n = 0;
1101 : 0 : state = DNS_LEN_HI;
1102 : :
1103 [ # # ]: 0 : if ( n < len )
1104 : : // More data to munch on.
1105 : 0 : DeliverStream(len - n, data + n, orig);
1106 : : }
1107 : :
1108 : 0 : DNS_Analyzer::DNS_Analyzer(Connection* conn)
1109 : 0 : : TCP_ApplicationAnalyzer(AnalyzerTag::DNS, conn)
1110 : : {
1111 : 0 : interp = new DNS_Interpreter(this);
1112 : 0 : contents_dns_orig = contents_dns_resp = 0;
1113 : 0 : did_session_done = 0;
1114 : :
1115 [ # # # # ]: 0 : if ( Conn()->ConnTransport() == TRANSPORT_TCP )
1116 : : {
1117 : 0 : contents_dns_orig = new Contents_DNS(conn, true, interp);
1118 : 0 : contents_dns_resp = new Contents_DNS(conn, false, interp);
1119 : 0 : AddSupportAnalyzer(contents_dns_orig);
1120 : 0 : AddSupportAnalyzer(contents_dns_resp);
1121 : : }
1122 : : else
1123 : : {
1124 : 0 : ADD_ANALYZER_TIMER(&DNS_Analyzer::ExpireTimer,
1125 : : network_time + dns_session_timeout, 1,
1126 : : TIMER_DNS_EXPIRE);
1127 : : }
1128 : 0 : }
1129 : :
1130 : 0 : DNS_Analyzer::~DNS_Analyzer()
1131 : : {
1132 : 0 : delete interp;
1133 [ # # ][ # # ]: 0 : }
[ # # ]
1134 : :
1135 : 0 : void DNS_Analyzer::Init()
1136 : : {
1137 [ # # ][ # # ]: 0 : if ( transformed_pkt_dump && RewritingTrace() &&
[ # # ][ # # ]
1138 : : Conn()->ConnTransport() == TRANSPORT_UDP )
1139 : : Conn()->GetRootAnalyzer()->SetTraceRewriter(
1140 : : new DNS_Rewriter(this, transformed_pkt_dump_MTU,
1141 : 0 : transformed_pkt_dump));
1142 : 0 : }
1143 : :
1144 : 0 : void DNS_Analyzer::Done()
1145 : : {
1146 : 0 : TCP_ApplicationAnalyzer::Done();
1147 : :
1148 [ # # # # ]: 0 : if ( Conn()->ConnTransport() == TRANSPORT_UDP && ! did_session_done )
[ # # ]
1149 : 0 : Event(udp_session_done);
1150 : : else
1151 : 0 : interp->Timeout();
1152 : 0 : }
1153 : :
1154 : : void DNS_Analyzer::DeliverPacket(int len, const u_char* data, bool orig,
1155 : 0 : int seq, const IP_Hdr* ip, int caplen)
1156 : : {
1157 : 0 : TCP_ApplicationAnalyzer::DeliverPacket(len, data, orig, seq, ip, caplen);
1158 : :
1159 [ # # ]: 0 : if ( orig )
1160 : : {
1161 [ # # ][ # # ]: 0 : if ( ! interp->ParseMessage(data, len, 1) && non_dns_request )
[ # # ]
1162 : : {
1163 : 0 : val_list* vl = new val_list;
1164 : 0 : vl->append(BuildConnVal());
1165 : 0 : vl->append(new StringVal(len, (const char*) data));
1166 : 0 : ConnectionEvent(non_dns_request, vl);
1167 : : }
1168 : : }
1169 : :
1170 : : else
1171 : 0 : interp->ParseMessage(data, len, 0);
1172 : 0 : }
1173 : :
1174 : :
1175 : : void DNS_Analyzer::ConnectionClosed(TCP_Endpoint* endpoint, TCP_Endpoint* peer,
1176 : 0 : int gen_event)
1177 : : {
1178 : 0 : TCP_ApplicationAnalyzer::ConnectionClosed(endpoint, peer, gen_event);
1179 : :
1180 [ # # # # ]: 0 : assert(contents_dns_orig && contents_dns_resp);
[ # # ]
1181 : 0 : contents_dns_orig->Flush();
1182 : 0 : contents_dns_resp->Flush();
1183 : 0 : }
1184 : :
1185 : 0 : void DNS_Analyzer::ExpireTimer(double t)
1186 : : {
1187 : : // The - 1.0 in the following is to allow 1 second for the
1188 : : // common case of a single request followed by a single reply,
1189 : : // so we don't needlessly set the timer twice in that case.
1190 [ # # ][ # # ]: 0 : if ( t - Conn()->LastTime() >= dns_session_timeout - 1.0 || terminating )
[ # # ]
1191 : : {
1192 : 0 : Event(connection_timeout);
1193 : 0 : sessions->Remove(Conn());
1194 : : }
1195 : : else
1196 : 0 : ADD_ANALYZER_TIMER(&DNS_Analyzer::ExpireTimer,
1197 : : t + dns_session_timeout, 1, TIMER_DNS_EXPIRE);
1198 : 0 : }
1199 : :
1200 : : #include "dns-rw.bif.func_def"
|