LCOV - code coverage report
Current view: top level - src - DNS.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 0 594 0.0 %
Date: 2010-12-13 Functions: 0 50 0.0 %
Branches: 0 275 0.0 %

           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"

Generated by: LCOV version 1.8