LCOV - code coverage report
Current view: top level - src - Sessions.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 296 673 44.0 %
Date: 2010-12-13 Functions: 20 43 46.5 %
Branches: 180 555 32.4 %

           Branch data     Line data    Source code
       1                 :            : // $Id: Sessions.cc 7075 2010-09-13 02:39:38Z vern $
       2                 :            : //
       3                 :            : // See the file "COPYING" in the main distribution directory for copyright.
       4                 :            : 
       5                 :            : 
       6                 :            : #include "config.h"
       7                 :            : 
       8                 :            : #include <arpa/inet.h>
       9                 :            : 
      10                 :            : #include <stdlib.h>
      11                 :            : #include <unistd.h>
      12                 :            : 
      13                 :            : #include "Net.h"
      14                 :            : #include "Event.h"
      15                 :            : #include "Timer.h"
      16                 :            : #include "NetVar.h"
      17                 :            : #include "Sessions.h"
      18                 :            : #include "Active.h"
      19                 :            : #include "OSFinger.h"
      20                 :            : 
      21                 :            : #include "ICMP.h"
      22                 :            : #include "UDP.h"
      23                 :            : 
      24                 :            : #include "DNS-binpac.h"
      25                 :            : #include "HTTP-binpac.h"
      26                 :            : 
      27                 :            : #include "SteppingStone.h"
      28                 :            : #include "BackDoor.h"
      29                 :            : #include "InterConn.h"
      30                 :            : #include "Discard.h"
      31                 :            : #include "RuleMatcher.h"
      32                 :            : #include "ConnCompressor.h"
      33                 :            : #include "DPM.h"
      34                 :            : 
      35                 :            : #include "PacketSort.h"
      36                 :            : 
      37                 :            : // These represent NetBIOS services on ephemeral ports.  They're numbered
      38                 :            : // so that we can use a single int to hold either an actual TCP/UDP server
      39                 :            : // port or one of these.
      40                 :            : enum NetBIOS_Service {
      41                 :            :         NETBIOS_SERVICE_START = 0x10000L,       // larger than any port
      42                 :            :         NETBIOS_SERVICE_DCE_RPC,
      43                 :            : };
      44                 :            : 
      45                 :            : NetSessions* sessions;
      46                 :            : 
      47                 :            : 
      48 [ #  # ][ #  # ]:          0 : class NetworkTimer : public Timer {
      49                 :            : public:
      50                 :          0 :         NetworkTimer(NetSessions* arg_sess, double arg_t)
      51                 :          0 :                 : Timer(arg_t, TIMER_NETWORK)
      52                 :          0 :                 { sess = arg_sess; }
      53                 :            : 
      54                 :            :         void Dispatch(double t, int is_expire);
      55                 :            : 
      56                 :            : protected:
      57                 :            :         NetSessions* sess;
      58                 :            : };
      59                 :            : 
      60                 :          0 : void NetworkTimer::Dispatch(double t, int is_expire)
      61                 :            :         {
      62         [ #  # ]:          0 :         if ( is_expire )
      63                 :          0 :                 return;
      64                 :            : 
      65                 :          0 :         sess->HeartBeat(t);
      66                 :            :         }
      67                 :            : 
      68                 :          0 : void TimerMgrExpireTimer::Dispatch(double t, int is_expire)
      69                 :            :         {
      70         [ #  # ]:          0 :         if ( mgr->LastAdvance() + timer_mgr_inactivity_timeout < timer_mgr->Time() )
      71                 :            :                 {
      72                 :            :                 // Expired.
      73                 :          0 :                 DBG_LOG(DBG_TM, "TimeMgr %p has timed out", mgr);
      74                 :          0 :                 mgr->Expire();
      75                 :            : 
      76                 :            :                 // Make sure events are executed.  They depend on the TimerMgr.
      77                 :          0 :                 ::mgr.Drain();
      78                 :            : 
      79                 :          0 :                 sessions->timer_mgrs.erase(mgr->GetTag());
      80         [ #  # ]:          0 :                 delete mgr;
      81                 :            :                 }
      82                 :            :         else
      83                 :            :                 {
      84                 :            :                 // Reinstall timer.
      85         [ #  # ]:          0 :                 if ( ! is_expire )
      86                 :            :                         {
      87                 :            :                         double n = mgr->LastAdvance() +
      88                 :          0 :                                         timer_mgr_inactivity_timeout;
      89                 :          0 :                         timer_mgr->Add(new TimerMgrExpireTimer(n, mgr));
      90                 :            :                         }
      91                 :            :                 }
      92                 :          0 :         }
      93                 :            : 
      94                 :          1 : NetSessions::NetSessions()
      95                 :            :         {
      96                 :          1 :         TypeList* t = new TypeList();
      97                 :          1 :         t->Append(base_type(TYPE_COUNT));    // source IP address
      98                 :          1 :         t->Append(base_type(TYPE_COUNT));    // dest IP address
      99                 :          1 :         t->Append(base_type(TYPE_COUNT));    // source and dest ports
     100                 :            : 
     101                 :          1 :         ch = new CompositeHash(t);
     102                 :            : 
     103                 :          1 :         Unref(t);
     104                 :            : 
     105                 :          1 :         tcp_conns.SetDeleteFunc(bro_obj_delete_func);
     106                 :          1 :         udp_conns.SetDeleteFunc(bro_obj_delete_func);
     107                 :          1 :         fragments.SetDeleteFunc(bro_obj_delete_func);
     108                 :            : 
     109   [ +  -  -  + ]:          1 :         if ( (reading_live || pseudo_realtime) && net_stats_update )
                 [ #  # ]
           [ -  +  #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     110                 :          0 :                 timer_mgr->Add(new NetworkTimer(this, 1.0));
     111                 :            : 
     112 [ -  + ][ #  # ]:          1 :         if ( stp_correlate_pair )
     113                 :          0 :                 stp_manager = new SteppingStoneManager();
     114                 :            :         else
     115                 :          1 :                 stp_manager = 0;
     116                 :            : 
     117                 :          1 :         discarder = new Discarder();
     118   [ +  -  #  # ]:          1 :         if ( ! discarder->IsActive() )
     119                 :            :                 {
     120 [ +  - ][ #  # ]:          1 :                 delete discarder;
     121                 :          1 :                 discarder = 0;
     122                 :            :                 }
     123                 :            : 
     124                 :          1 :         packet_filter = 0;
     125                 :            : 
     126                 :            :         build_backdoor_analyzer =
     127                 :            :                 backdoor_stats || rlogin_signature_found ||
     128                 :            :                 telnet_signature_found || ssh_signature_found ||
     129                 :            :                 root_backdoor_signature_found || ftp_signature_found ||
     130                 :            :                 napster_signature_found || kazaa_signature_found ||
     131 [ +  - ][ +  - ]:          1 :                 http_signature_found || http_proxy_signature_found;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     132                 :            : 
     133                 :          1 :         dump_this_packet = 0;
     134                 :          1 :         num_packets_processed = 0;
     135                 :            : 
     136 [ -  + ][ #  # ]:          1 :         if ( OS_version_found )
     137                 :            :                 {
     138                 :          0 :                 SYN_OS_Fingerprinter = new OSFingerprint(SYN_FINGERPRINT_MODE);
     139   [ #  #  #  # ]:          0 :                 if ( SYN_OS_Fingerprinter->Error() )
     140                 :          0 :                         exit(1);
     141                 :            :                 }
     142                 :            :         else
     143                 :          1 :                 SYN_OS_Fingerprinter = 0;
     144                 :            : 
     145 [ -  + ][ #  # ]:          1 :         if ( pkt_profile_mode && pkt_profile_freq > 0 && pkt_profile_file )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     146                 :            :                 pkt_profiler = new PacketProfiler(pkt_profile_mode,
     147                 :          0 :                                 pkt_profile_freq, pkt_profile_file->AsFile());
     148                 :            :         else
     149                 :          1 :                 pkt_profiler = 0;
     150                 :            : 
     151 [ +  - ][ +  - ]:          1 :         if ( arp_request || arp_reply || bad_arp )
         [ -  + ][ -  + ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     152                 :          0 :                 arp_analyzer = new ARP_Analyzer();
     153                 :            :         else
     154                 :          1 :                 arp_analyzer = 0;
     155                 :          1 :         }
     156                 :            : 
     157                 :          1 : NetSessions::~NetSessions()
     158                 :            :         {
     159 [ +  - ][ #  # ]:          1 :         delete ch;
     160 [ -  + ][ #  # ]:          1 :         delete packet_filter;
     161 [ -  + ][ #  # ]:          1 :         delete SYN_OS_Fingerprinter;
     162 [ -  + ][ #  # ]:          1 :         delete pkt_profiler;
     163                 :          1 :         Unref(arp_analyzer);
     164                 :          1 :         }
     165                 :            : 
     166                 :          1 : void NetSessions::Done()
     167                 :            :         {
     168         [ -  + ]:          1 :         delete stp_manager;
     169         [ -  + ]:          1 :         delete discarder;
     170                 :          1 :         }
     171                 :            : 
     172                 :            : namespace       // private namespace
     173                 :            :         {
     174                 :          0 :         bool looks_like_IPv4_packet(int len, const struct ip* ip_hdr)
     175                 :            :                 {
     176         [ #  # ]:          0 :                 if ( len < int(sizeof(struct ip)) )
     177                 :          0 :                         return false;
     178 [ #  # ][ #  # ]:          0 :                 return ip_hdr->ip_v == 4 && ntohs(ip_hdr->ip_len) == len;
     179                 :            :                 }
     180                 :            :         }
     181                 :            : 
     182                 :            : void NetSessions::DispatchPacket(double t, const struct pcap_pkthdr* hdr,
     183                 :            :                         const u_char* pkt, int hdr_size,
     184                 :      21347 :                         PktSrc* src_ps, PacketSortElement* pkt_elem)
     185                 :            :         {
     186                 :      21347 :         const struct ip* ip_hdr = 0;
     187                 :      21347 :         const u_char* ip_data = 0;
     188                 :      21347 :         int proto = 0;
     189                 :            : 
     190         [ +  - ]:      21347 :         if ( hdr->caplen >= hdr_size + sizeof(struct ip) )
     191                 :            :                 {
     192                 :      21347 :                 ip_hdr = reinterpret_cast<const struct ip*>(pkt + hdr_size);
     193         [ +  - ]:      21347 :                 if ( hdr->caplen >= unsigned(hdr_size + (ip_hdr->ip_hl << 2)) )
     194                 :      21347 :                         ip_data = pkt + hdr_size + (ip_hdr->ip_hl << 2);
     195                 :            :                 }
     196                 :            : 
     197 [ -  + ][ #  # ]:      21347 :         if ( encap_hdr_size > 0 && ip_data )
     198                 :            :                 {
     199                 :            :                 // We're doing tunnel encapsulation.  Check whether there's
     200                 :            :                 // a particular associated port.
     201                 :            :                 //
     202                 :            :                 // Should we discourage the use of encap_hdr_size for UDP
     203                 :            :                 // tunnneling?  It is probably better handled by enabling
     204                 :            :                 // parse_udp_tunnels instead of specifying a fixed
     205                 :            :                 // encap_hdr_size.
     206         [ #  # ]:          0 :                 if ( udp_tunnel_port > 0 )
     207                 :            :                         {
     208         [ #  # ]:          0 :                         ASSERT(ip_hdr);
     209         [ #  # ]:          0 :                         if ( ip_hdr->ip_p == IPPROTO_UDP )
     210                 :            :                                 {
     211                 :            :                                 const struct udphdr* udp_hdr =
     212                 :            :                                         reinterpret_cast<const struct udphdr*>
     213                 :          0 :                                         (ip_data);
     214                 :            : 
     215         [ #  # ]:          0 :                                 if ( ntohs(udp_hdr->uh_dport) == udp_tunnel_port )
     216                 :            :                                         {
     217                 :            :                                         // A match.
     218                 :          0 :                                         hdr_size += encap_hdr_size;
     219                 :            :                                         }
     220                 :            :                                 }
     221                 :            :                         }
     222                 :            : 
     223                 :            :                 else
     224                 :            :                         // Blanket encapsulation (e.g., for VLAN).
     225                 :          0 :                         hdr_size += encap_hdr_size;
     226                 :            :                 }
     227                 :            : 
     228                 :            :         // Check IP packets encapsulated through UDP tunnels.
     229                 :            :         // Specifying a udp_tunnel_port is optional but recommended (to avoid
     230                 :            :         // the cost of checking every UDP packet).
     231 [ -  + ][ #  # ]:      21347 :         else if ( parse_udp_tunnels && ip_data && ip_hdr->ip_p == IPPROTO_UDP )
                 [ #  # ]
     232                 :            :                 {
     233                 :            :                 const struct udphdr* udp_hdr =
     234                 :          0 :                         reinterpret_cast<const struct udphdr*>(ip_data);
     235                 :            : 
     236 [ #  # ][ #  # ]:          0 :                 if ( udp_tunnel_port == 0 || // 0 matches any port
                 [ #  # ]
     237                 :            :                      udp_tunnel_port == ntohs(udp_hdr->uh_dport) )
     238                 :            :                         {
     239                 :            :                         const u_char* udp_data =
     240                 :          0 :                                 ip_data + sizeof(struct udphdr);
     241                 :            :                         const struct ip* ip_encap =
     242                 :          0 :                                 reinterpret_cast<const struct ip*>(udp_data);
     243                 :            :                         const int ip_encap_len =
     244                 :          0 :                                 ntohs(udp_hdr->uh_ulen) - sizeof(struct udphdr);
     245                 :            :                         const int ip_encap_caplen =
     246                 :          0 :                                 hdr->caplen - (udp_data - pkt);
     247                 :            : 
     248         [ #  # ]:          0 :                         if ( looks_like_IPv4_packet(ip_encap_len, ip_encap) )
     249                 :          0 :                                 hdr_size = udp_data - pkt;
     250                 :            :                         }
     251                 :            :                 }
     252                 :            : 
     253         [ +  - ]:      21347 :         if ( src_ps->FilterType() == TYPE_FILTER_NORMAL )
     254                 :      21347 :                 NextPacket(t, hdr, pkt, hdr_size, pkt_elem);
     255                 :            :         else
     256                 :          0 :                 NextPacketSecondary(t, hdr, pkt, hdr_size, src_ps);
     257                 :      21347 :         }
     258                 :            : 
     259                 :            : void NetSessions::NextPacket(double t, const struct pcap_pkthdr* hdr,
     260                 :            :                              const u_char* const pkt, int hdr_size,
     261                 :      21347 :                              PacketSortElement* pkt_elem)
     262                 :            :         {
     263                 :      21347 :         SegmentProfiler(segment_logger, "processing-packet");
     264         [ -  + ]:      21347 :         if ( pkt_profiler )
     265                 :          0 :                 pkt_profiler->ProfilePkt(t, hdr->caplen);
     266                 :            : 
     267                 :      21347 :         ++num_packets_processed;
     268                 :            : 
     269                 :      21347 :         dump_this_packet = 0;
     270                 :            : 
     271         [ -  + ]:      21347 :         if ( record_all_packets )
     272                 :          0 :                 DumpPacket(hdr, pkt);
     273                 :            : 
     274 [ -  + ][ #  # ]:      21347 :         if ( pkt_elem && pkt_elem->IPHdr() )
                 [ -  + ]
     275                 :            :                 // Fast path for "normal" IP packets if an IP_Hdr is
     276                 :            :                 // already extracted when doing PacketSort. Otherwise
     277                 :            :                 // the code below tries to extract the IP header, the
     278                 :            :                 // difference here is that header extraction in
     279                 :            :                 // PacketSort does not generate Weird events.
     280                 :            : 
     281                 :          0 :                 DoNextPacket(t, hdr, pkt_elem->IPHdr(), pkt, hdr_size);
     282                 :            : 
     283                 :            :         else
     284                 :            :                 {
     285                 :            :                 // ### The following isn't really correct.  What we *should*
     286                 :            :                 // do is understanding the different link layers in order to
     287                 :            :                 // find the network-layer protocol ID.  That's a big
     288                 :            :                 // portability pain, though, unless we just assume everything's
     289                 :            :                 // Ethernet .... not great, given the potential need to deal
     290                 :            :                 // with PPP or FDDI (for some older traces).  So instead
     291                 :            :                 // we look to see if what we have is consistent with an
     292                 :            :                 // IPv4 packet.  If not, it's either ARP or IPv6 or weird.
     293                 :            : 
     294                 :      21347 :                 uint32 caplen = hdr->caplen - hdr_size;
     295         [ -  + ]:      21347 :                 if ( caplen < sizeof(struct ip) )
     296                 :            :                         {
     297                 :          0 :                         Weird("truncated_IP", hdr, pkt);
     298                 :          0 :                         return;
     299                 :            :                         }
     300                 :            : 
     301                 :      21347 :                 const struct ip* ip = (const struct ip*) (pkt + hdr_size);
     302         [ +  + ]:      21347 :                 if ( ip->ip_v == 4 )
     303                 :            :                         {
     304                 :      20378 :                         IP_Hdr ip_hdr(ip);
     305                 :      20378 :                         DoNextPacket(t, hdr, &ip_hdr, pkt, hdr_size);
     306                 :            :                         }
     307                 :            : 
     308 [ -  + ][ #  # ]:        969 :                 else if ( arp_analyzer && arp_analyzer->IsARP(pkt, hdr_size) )
                 [ -  + ]
     309                 :          0 :                         arp_analyzer->NextPacket(t, hdr, pkt, hdr_size);
     310                 :            : 
     311                 :            :                 else
     312                 :            :                         {
     313                 :            : #ifdef BROv6
     314                 :            :                         IP_Hdr ip_hdr((const struct ip6_hdr*) (pkt + hdr_size));
     315                 :            :                         DoNextPacket(t, hdr, &ip_hdr, pkt, hdr_size);
     316                 :            : #else
     317                 :        969 :                         Weird("non_IPv4_packet", hdr, pkt);
     318                 :        969 :                         return;
     319                 :            : #endif
     320                 :            :                         }
     321                 :            :                 }
     322                 :            : 
     323 [ +  + ][ +  - ]:      20378 :         if ( dump_this_packet && ! record_all_packets )
     324                 :      21347 :                 DumpPacket(hdr, pkt);
     325                 :            :         }
     326                 :            : 
     327                 :            : void NetSessions::NextPacketSecondary(double /* t */, const struct pcap_pkthdr* hdr,
     328                 :            :                                 const u_char* const pkt, int hdr_size,
     329                 :          0 :                                 const PktSrc* src_ps)
     330                 :            :         {
     331                 :          0 :         SegmentProfiler(segment_logger, "processing-secondary-packet");
     332                 :            : 
     333                 :          0 :         ++num_packets_processed;
     334                 :            : 
     335                 :          0 :         uint32 caplen = hdr->caplen - hdr_size;
     336         [ #  # ]:          0 :         if ( caplen < sizeof(struct ip) )
     337                 :            :                 {
     338                 :          0 :                 Weird("truncated_IP", hdr, pkt);
     339                 :          0 :                 return;
     340                 :            :                 }
     341                 :            : 
     342                 :          0 :         const struct ip* ip = (const struct ip*) (pkt + hdr_size);
     343         [ #  # ]:          0 :         if ( ip->ip_v == 4 )
     344                 :            :                 {
     345                 :          0 :                 const secondary_program_list& spt = src_ps->ProgramTable();
     346                 :            : 
     347         [ #  # ]:          0 :                 loop_over_list(spt, i)
     348                 :            :                         {
     349                 :          0 :                         SecondaryProgram* sp = spt[i];
     350         [ #  # ]:          0 :                         if ( ! net_packet_match(sp->Program(), pkt,
     351                 :            :                                                 hdr->len, hdr->caplen) )
     352                 :          0 :                                 continue;
     353                 :            : 
     354                 :          0 :                         val_list* args = new val_list;
     355                 :            :                         StringVal* cmd_val =
     356                 :          0 :                                 new StringVal(sp->Event()->Filter());
     357                 :          0 :                         args->append(cmd_val);
     358                 :          0 :                         args->append(BuildHeader(ip));
     359                 :            :                         // ### Need to queue event here.
     360                 :          0 :                         sp->Event()->Event()->Call(args);
     361         [ #  # ]:          0 :                         delete args;
     362                 :            :                         }
     363                 :            :                 }
     364                 :            :         }
     365                 :            : 
     366                 :       1025 : int NetSessions::CheckConnectionTag(Connection* conn)
     367                 :            :         {
     368         [ -  + ]:       1025 :         if ( current_iosrc->GetCurrentTag() )
     369                 :            :                 {
     370                 :            :                 // Packet is tagged.
     371         [ #  # ]:          0 :                 if ( conn->GetTimerMgr() == timer_mgr )
     372                 :            :                         {
     373                 :            :                         // Connection uses global timer queue.  But the
     374                 :            :                         // packet has a tag that means we got it externally,
     375                 :            :                         // probably from the Time Machine.
     376                 :          0 :                         DBG_LOG(DBG_TM, "got packet with tag %s for already"
     377                 :            :                                         "known connection, reinstantiating",
     378                 :            :                                         current_iosrc->GetCurrentTag()->c_str());
     379                 :          0 :                         return 0;
     380                 :            :                         }
     381                 :            :                 else
     382                 :            :                         {
     383                 :            :                         // Connection uses local timer queue.
     384                 :            :                         TimerMgrMap::iterator i =
     385                 :          0 :                                 timer_mgrs.find(*current_iosrc->GetCurrentTag());
     386   [ #  #  #  # ]:          0 :                         if ( i != timer_mgrs.end() &&
                 [ #  # ]
     387                 :            :                              conn->GetTimerMgr() != i->second )
     388                 :            :                                 {
     389                 :            :                                 // Connection uses different local queue
     390                 :            :                                 // than the tag for the current packet
     391                 :            :                                 // indicates.
     392                 :            :                                 //
     393                 :            :                                 // This can happen due to:
     394                 :            :                                 //     (1) getting same packets with
     395                 :            :                                 //              different tags
     396                 :            :                                 //     (2) timer mgr having already expired
     397                 :          0 :                                 DBG_LOG(DBG_TM, "packet ignored due old/inconsistent tag");
     398                 :          0 :                                 return -1;
     399                 :            :                                 }
     400                 :            : 
     401                 :          0 :                         return 1;
     402                 :            :                         }
     403                 :            :                 }
     404                 :            : 
     405                 :            :         // Packet is not tagged.
     406         [ -  + ]:       1025 :         if ( conn->GetTimerMgr() != timer_mgr )
     407                 :            :                 {
     408                 :            :                 // Connection does not use the global timer queue.  That
     409                 :            :                 // means that this is a live packet belonging to a
     410                 :            :                 // connection for which we have already switched to
     411                 :            :                 // processing external input.
     412                 :          0 :                 DBG_LOG(DBG_TM, "packet ignored due to processing it in external data");
     413                 :          0 :                 return -1;
     414                 :            :                 }
     415                 :            : 
     416                 :       1025 :         return 1;
     417                 :            :         }
     418                 :            : 
     419                 :            : 
     420                 :          0 : static bool looks_like_IPv4_packet(int len, const struct ip* ip_hdr)
     421                 :            :         {
     422         [ #  # ]:          0 :         if ( (unsigned int) len < sizeof(struct ip) )
     423                 :          0 :                 return false;
     424                 :            : 
     425 [ #  # ][ #  # ]:          0 :         if ( ip_hdr->ip_v == 4 && ntohs(ip_hdr->ip_len) == len )
                 [ #  # ]
     426                 :          0 :                 return true;
     427                 :            :         else
     428                 :          0 :                 return false;
     429                 :            :         }
     430                 :            : 
     431                 :            : void NetSessions::DoNextPacket(double t, const struct pcap_pkthdr* hdr,
     432                 :            :                                 const IP_Hdr* ip_hdr, const u_char* const pkt,
     433                 :      20378 :                                 int hdr_size)
     434                 :            :         {
     435                 :      20378 :         uint32 caplen = hdr->caplen - hdr_size;
     436                 :      20378 :         const struct ip* ip4 = ip_hdr->IP4_Hdr();
     437                 :            : 
     438                 :      20378 :         uint32 len = ip_hdr->TotalLen();
     439         [ -  + ]:      20378 :         if ( hdr->len < len + hdr_size )
     440                 :            :                 {
     441                 :          0 :                 Weird("truncated_IP", hdr, pkt);
     442                 :          0 :                 return;
     443                 :            :                 }
     444                 :            : 
     445                 :            :         // Ignore if packet matches packet filter.
     446 [ -  + ][ #  # ]:      20378 :         if ( packet_filter && packet_filter->Match(ip_hdr, len, caplen) )
                 [ -  + ]
     447                 :          0 :                  return;
     448                 :            : 
     449                 :      20378 :         int ip_hdr_len = ip_hdr->HdrLen();
     450   [ +  -  +  - ]:      20378 :         if ( ! ignore_checksums && ip4 &&
         [ -  + ][ -  + ]
     451                 :            :              ones_complement_checksum((void*) ip4, ip_hdr_len, 0) != 0xffff )
     452                 :            :                 {
     453                 :          0 :                 Weird("bad_IP_checksum", hdr, pkt);
     454                 :          0 :                 return;
     455                 :            :                 }
     456                 :            : 
     457 [ -  + ][ #  # ]:      20378 :         if ( discarder && discarder->NextPacket(ip_hdr, len, caplen) )
                 [ -  + ]
     458                 :          0 :                 return;
     459                 :            : 
     460                 :      20378 :         int proto = ip_hdr->NextProto();
     461   [ +  +  +  + ]:      20378 :         if ( proto != IPPROTO_TCP && proto != IPPROTO_UDP &&
                 [ +  + ]
     462                 :            :              proto != IPPROTO_ICMP )
     463                 :            :                 {
     464                 :        108 :                 dump_this_packet = 1;
     465                 :        108 :                 return;
     466                 :            :                 }
     467                 :            : 
     468                 :            :         // Check for TTL/MTU problems from Active Mapping
     469                 :            : #ifdef ACTIVE_MAPPING
     470                 :            :         const NumericData* numeric = 0;
     471                 :            :         if ( ip4 )
     472                 :            :                 {
     473                 :            :                 get_map_result(ip4->ip_dst.s_addr, numeric);
     474                 :            : 
     475                 :            :                 if ( numeric->hops && ip4->ip_ttl < numeric->hops )
     476                 :            :                         {
     477                 :            :                         debug_msg("Packet destined for %s had ttl %d but there are %d hops to host.\n",
     478                 :            :                         inet_ntoa(ip4->ip_dst), ip4->ip_ttl, numeric->hops);
     479                 :            :                         return;
     480                 :            :                         }
     481                 :            :                 }
     482                 :            : #endif
     483                 :            : 
     484                 :      20270 :         FragReassembler* f = 0;
     485                 :      20270 :         uint32 frag_field = ip_hdr->FragField();
     486                 :            : 
     487                 :            : #ifdef ACTIVE_MAPPING
     488                 :            :         if ( ip4 && numeric && numeric->path_MTU && (frag_field & IP_DF) )
     489                 :            :                 {
     490                 :            :                 if ( htons(ip4->ip_len) > numeric->path_MTU )
     491                 :            :                         {
     492                 :            :                         debug_msg("Packet destined for %s has DF flag but its size %d is greater than pmtu of %d\n",
     493                 :            :                         inet_ntoa(ip4->ip_dst), htons(ip4->ip_len), numeric->path_MTU);
     494                 :            :                         return;
     495                 :            :                         }
     496                 :            :                 }
     497                 :            : #endif
     498                 :            : 
     499         [ -  + ]:      20270 :         if ( (frag_field & 0x3fff) != 0 )
     500                 :            :                 {
     501                 :          0 :                 dump_this_packet = 1;   // always record fragments
     502                 :            : 
     503         [ #  # ]:          0 :                 if ( caplen < len )
     504                 :            :                         {
     505                 :          0 :                         Weird("incompletely_captured_fragment", ip_hdr);
     506                 :            : 
     507                 :            :                         // Don't try to reassemble, that's doomed.
     508                 :            :                         // Discard all except the first fragment (which
     509                 :            :                         // is useful in analyzing header-only traces)
     510         [ #  # ]:          0 :                         if ( (frag_field & 0x1fff) != 0 )
     511                 :          0 :                                 return;
     512                 :            :                         }
     513                 :            :                 else
     514                 :            :                         {
     515                 :          0 :                         f = NextFragment(t, ip_hdr, pkt + hdr_size, frag_field);
     516                 :          0 :                         const IP_Hdr* ih = f->ReassembledPkt();
     517         [ #  # ]:          0 :                         if ( ! ih )
     518                 :            :                                 // It didn't reassemble into anything yet.
     519                 :          0 :                                 return;
     520                 :            : 
     521                 :          0 :                         ip4 = ih->IP4_Hdr();
     522                 :          0 :                         ip_hdr = ih;
     523                 :            : 
     524                 :          0 :                         caplen = len = ip_hdr->TotalLen();
     525                 :          0 :                         ip_hdr_len = ip_hdr->HdrLen();
     526                 :            :                         }
     527                 :            :                 }
     528                 :            : 
     529                 :      20270 :         len -= ip_hdr_len;      // remove IP header
     530                 :      20270 :         caplen -= ip_hdr_len;
     531                 :            : 
     532                 :            :         uint32 min_hdr_len = (proto == IPPROTO_TCP) ?  sizeof(struct tcphdr) :
     533         [ +  + ]:      20270 :                 (proto == IPPROTO_UDP ? sizeof(struct udphdr) : ICMP_MINLEN);
     534                 :            : 
     535         [ -  + ]:      20270 :         if ( len < min_hdr_len )
     536                 :            :                 {
     537                 :          0 :                 Weird("truncated_header", hdr, pkt);
     538         [ #  # ]:          0 :                 if ( f )
     539                 :          0 :                         Remove(f);      // ###
     540                 :          0 :                 return;
     541                 :            :                 }
     542         [ -  + ]:      20270 :         if ( caplen < min_hdr_len )
     543                 :            :                 {
     544                 :          0 :                 Weird("internally_truncated_header", hdr, pkt);
     545         [ #  # ]:          0 :                 if ( f )
     546                 :          0 :                         Remove(f);      // ###
     547                 :          0 :                 return;
     548                 :            :                 }
     549                 :            : 
     550                 :      20270 :         const u_char* data = ip_hdr->Payload();
     551                 :            : 
     552                 :            :         ConnID id;
     553                 :      20270 :         id.src_addr = ip_hdr->SrcAddr();
     554                 :      20270 :         id.dst_addr = ip_hdr->DstAddr();
     555                 :      20270 :         Dictionary* d = 0;
     556                 :      20270 :         bool pass_to_conn_compressor = false;
     557                 :            : 
     558   [ +  +  +  - ]:      20270 :         switch ( proto ) {
     559                 :            :         case IPPROTO_TCP:
     560                 :            :                 {
     561                 :      18556 :                 const struct tcphdr* tp = (const struct tcphdr *) data;
     562                 :      18556 :                 id.src_port = tp->th_sport;
     563                 :      18556 :                 id.dst_port = tp->th_dport;
     564                 :      18556 :                 id.is_one_way = 0;
     565                 :      18556 :                 d = &tcp_conns;
     566 [ +  - ][ +  - ]:      18556 :                 pass_to_conn_compressor = ip4 && use_connection_compressor;
     567                 :      18556 :                 break;
     568                 :            :                 }
     569                 :            : 
     570                 :            :         case IPPROTO_UDP:
     571                 :            :                 {
     572                 :       1683 :                 const struct udphdr* up = (const struct udphdr *) data;
     573                 :       1683 :                 id.src_port = up->uh_sport;
     574                 :       1683 :                 id.dst_port = up->uh_dport;
     575                 :       1683 :                 id.is_one_way = 0;
     576                 :       1683 :                 d = &udp_conns;
     577                 :       1683 :                 break;
     578                 :            :                 }
     579                 :            : 
     580                 :            :         case IPPROTO_ICMP:
     581                 :            :                 {
     582                 :         31 :                 const struct icmp* icmpp = (const struct icmp *) data;
     583                 :            : 
     584                 :         31 :                 id.src_port = icmpp->icmp_type;
     585                 :            :                 id.dst_port = ICMP_counterpart(icmpp->icmp_type,
     586                 :            :                                                 icmpp->icmp_code,
     587                 :         31 :                                                 id.is_one_way);
     588                 :            : 
     589                 :         31 :                 id.src_port = htons(id.src_port);
     590                 :         31 :                 id.dst_port = htons(id.dst_port);
     591                 :            : 
     592                 :         31 :                 d = &icmp_conns;
     593                 :         31 :                 break;
     594                 :            :                 }
     595                 :            : 
     596                 :            :         default:
     597                 :          0 :                 Weird(fmt("unknown_protocol %d", proto), hdr, pkt);
     598                 :          0 :                 return;
     599                 :            :         }
     600                 :            : 
     601                 :      20270 :         HashKey* h = id.BuildConnKey();
     602         [ -  + ]:      20270 :         if ( ! h )
     603                 :          0 :                 internal_error("hash computation failed");
     604                 :            : 
     605                 :      20270 :         Connection* conn = 0;
     606                 :            : 
     607                 :            :         // FIXME: The following is getting pretty complex. Need to split up
     608                 :            :         // into separate functions.
     609         [ +  + ]:      20270 :         if ( pass_to_conn_compressor )
     610                 :      18556 :                 conn = conn_compressor->NextPacket(t, h, ip_hdr, hdr, pkt);
     611                 :            :         else
     612                 :            :                 {
     613                 :       1714 :                 conn = (Connection*) d->Lookup(h);
     614         [ +  + ]:       1714 :                 if ( ! conn )
     615                 :            :                         {
     616                 :        689 :                         conn = NewConn(h, t, &id, data, proto);
     617         [ +  - ]:        689 :                         if ( conn )
     618                 :        689 :                                 d->Insert(h, conn);
     619                 :            :                         }
     620                 :            :                 else
     621                 :            :                         {
     622                 :            :                         // We already know that connection.
     623                 :       1025 :                         int consistent = CheckConnectionTag(conn);
     624         [ -  + ]:       1025 :                         if ( consistent < 0 )
     625                 :            :                                 {
     626         [ #  # ]:          0 :                                 delete h;
     627                 :          0 :                                 return;
     628                 :            :                                 }
     629                 :            : 
     630 [ +  - ][ -  + ]:       1025 :                         if ( ! consistent || conn->IsReuse(t, data) )
                 [ -  + ]
     631                 :            :                                 {
     632         [ #  # ]:          0 :                                 if ( consistent )
     633                 :          0 :                                         conn->Event(connection_reused, 0);
     634                 :            : 
     635                 :          0 :                                 Remove(conn);
     636                 :          0 :                                 conn = NewConn(h, t, &id, data, proto);
     637         [ #  # ]:          0 :                                 if ( conn )
     638                 :          0 :                                         d->Insert(h, conn);
     639                 :            :                                 }
     640                 :            :                         else
     641         [ +  - ]:       1025 :                                 delete h;
     642                 :            :                         }
     643                 :            : 
     644         [ -  + ]:       1714 :                 if ( ! conn )
     645         [ #  # ]:          0 :                         delete h;
     646                 :            :                 }
     647                 :            : 
     648         [ +  + ]:      20270 :         if ( ! conn )
     649                 :       1104 :                 return;
     650                 :            : 
     651                 :      19166 :         int record_packet = 1;  // whether to record the packet at all
     652                 :      19166 :         int record_content = 1; // whether to record its data
     653                 :            : 
     654                 :            :         int is_orig = addr_eq(id.src_addr, conn->OrigAddr()) &&
     655 [ +  + ][ +  - ]:      19166 :                         id.src_port == conn->OrigPort();
     656                 :            : 
     657 [ -  + ][ #  # ]:      19166 :         if ( new_packet && ip4 )
                 [ -  + ]
     658                 :          0 :                 conn->Event(new_packet, 0, BuildHeader(ip4));
     659                 :            : 
     660                 :            :         conn->NextPacket(t, is_orig, ip_hdr, len, caplen, data,
     661                 :            :                                 record_packet, record_content,
     662                 :      19166 :                                 hdr, pkt, hdr_size);
     663                 :            : 
     664                 :            :         // Override content record setting according to
     665                 :            :         // flags set by the policy script.
     666         [ -  + ]:      19166 :         if ( dump_original_packets_if_not_rewriting )
     667                 :          0 :                 record_packet = record_content = 1;
     668         [ -  + ]:      19166 :         if ( dump_selected_source_packets )
     669                 :          0 :                 record_packet = record_content = 0;
     670                 :            : 
     671         [ -  + ]:      19166 :         if ( f )
     672                 :            :                 {
     673                 :            :                 // Above we already recorded the fragment in its entirety.
     674                 :          0 :                 f->DeleteTimer();
     675                 :          0 :                 Remove(f);      // ###
     676                 :            :                 }
     677                 :            : 
     678 [ +  - ][ +  - ]:      19166 :         else if ( record_packet && ! conn->RewritingTrace() )
                 [ +  - ]
     679                 :            :                 {
     680         [ +  - ]:      19166 :                 if ( record_content )
     681                 :      19166 :                         dump_this_packet = 1;   // save the whole thing
     682                 :            : 
     683                 :            :                 else
     684                 :            :                         {
     685                 :          0 :                         int hdr_len = data - pkt;
     686                 :      20378 :                         DumpPacket(hdr, pkt, hdr_len);  // just save the header
     687                 :            :                         }
     688                 :            :                 }
     689                 :            :         }
     690                 :            : 
     691                 :          0 : Val* NetSessions::BuildHeader(const struct ip* ip)
     692                 :            :         {
     693                 :            :         static RecordType* pkt_hdr_type = 0;
     694                 :            :         static RecordType* ip_hdr_type = 0;
     695                 :            :         static RecordType* tcp_hdr_type = 0;
     696                 :            :         static RecordType* udp_hdr_type = 0;
     697                 :            :         static RecordType* icmp_hdr_type;
     698                 :            : 
     699         [ #  # ]:          0 :         if ( ! pkt_hdr_type )
     700                 :            :                 {
     701                 :          0 :                 pkt_hdr_type = internal_type("pkt_hdr")->AsRecordType();
     702                 :          0 :                 ip_hdr_type = internal_type("ip_hdr")->AsRecordType();
     703                 :          0 :                 tcp_hdr_type = internal_type("tcp_hdr")->AsRecordType();
     704                 :          0 :                 udp_hdr_type = internal_type("udp_hdr")->AsRecordType();
     705                 :          0 :                 icmp_hdr_type = internal_type("icmp_hdr")->AsRecordType();
     706                 :            :                 }
     707                 :            : 
     708                 :          0 :         RecordVal* pkt_hdr = new RecordVal(pkt_hdr_type);
     709                 :            : 
     710                 :          0 :         RecordVal* ip_hdr = new RecordVal(ip_hdr_type);
     711                 :            : 
     712                 :          0 :         int ip_hdr_len = ip->ip_hl * 4;
     713                 :          0 :         int ip_pkt_len = ntohs(ip->ip_len);
     714                 :            : 
     715                 :          0 :         ip_hdr->Assign(0, new Val(ip->ip_hl * 4, TYPE_COUNT));
     716                 :          0 :         ip_hdr->Assign(1, new Val(ip->ip_tos, TYPE_COUNT));
     717                 :          0 :         ip_hdr->Assign(2, new Val(ip_pkt_len, TYPE_COUNT));
     718                 :          0 :         ip_hdr->Assign(3, new Val(ntohs(ip->ip_id), TYPE_COUNT));
     719                 :          0 :         ip_hdr->Assign(4, new Val(ip->ip_ttl, TYPE_COUNT));
     720                 :          0 :         ip_hdr->Assign(5, new Val(ip->ip_p, TYPE_COUNT));
     721                 :          0 :         ip_hdr->Assign(6, new AddrVal(ip->ip_src.s_addr));
     722                 :          0 :         ip_hdr->Assign(7, new AddrVal(ip->ip_dst.s_addr));
     723                 :            : 
     724                 :          0 :         pkt_hdr->Assign(0, ip_hdr);
     725                 :            : 
     726                 :            :         // L4 header.
     727                 :          0 :         const u_char* data = ((const u_char*) ip) + ip_hdr_len;
     728                 :            : 
     729                 :          0 :         int proto = ip->ip_p;
     730   [ #  #  #  # ]:          0 :         switch ( proto ) {
     731                 :            :         case IPPROTO_TCP:
     732                 :            :                 {
     733                 :          0 :                 const struct tcphdr* tp = (const struct tcphdr*) data;
     734                 :          0 :                 RecordVal* tcp_hdr = new RecordVal(tcp_hdr_type);
     735                 :            : 
     736                 :          0 :                 int tcp_hdr_len = tp->th_off * 4;
     737                 :          0 :                 int data_len = ip_pkt_len - ip_hdr_len - tcp_hdr_len;
     738                 :            : 
     739                 :          0 :                 tcp_hdr->Assign(0, new PortVal(ntohs(tp->th_sport), TRANSPORT_TCP));
     740                 :          0 :                 tcp_hdr->Assign(1, new PortVal(ntohs(tp->th_dport), TRANSPORT_TCP));
     741                 :          0 :                 tcp_hdr->Assign(2, new Val(uint32(ntohl(tp->th_seq)), TYPE_COUNT));
     742                 :          0 :                 tcp_hdr->Assign(3, new Val(uint32(ntohl(tp->th_ack)), TYPE_COUNT));
     743                 :          0 :                 tcp_hdr->Assign(4, new Val(tcp_hdr_len, TYPE_COUNT));
     744                 :          0 :                 tcp_hdr->Assign(5, new Val(data_len, TYPE_COUNT));
     745                 :          0 :                 tcp_hdr->Assign(6, new Val(tp->th_flags, TYPE_COUNT));
     746                 :          0 :                 tcp_hdr->Assign(7, new Val(ntohs(tp->th_win), TYPE_COUNT));
     747                 :            : 
     748                 :          0 :                 pkt_hdr->Assign(1, tcp_hdr);
     749                 :          0 :                 break;
     750                 :            :                 }
     751                 :            : 
     752                 :            :         case IPPROTO_UDP:
     753                 :            :                 {
     754                 :          0 :                 const struct udphdr* up = (const struct udphdr*) data;
     755                 :          0 :                 RecordVal* udp_hdr = new RecordVal(udp_hdr_type);
     756                 :            : 
     757                 :          0 :                 udp_hdr->Assign(0, new PortVal(ntohs(up->uh_sport), TRANSPORT_UDP));
     758                 :          0 :                 udp_hdr->Assign(1, new PortVal(ntohs(up->uh_dport), TRANSPORT_UDP));
     759                 :          0 :                 udp_hdr->Assign(2, new Val(ntohs(up->uh_ulen), TYPE_COUNT));
     760                 :            : 
     761                 :          0 :                 pkt_hdr->Assign(2, udp_hdr);
     762                 :          0 :                 break;
     763                 :            :                 }
     764                 :            : 
     765                 :            :         case IPPROTO_ICMP:
     766                 :            :                 {
     767                 :          0 :                 const struct icmp* icmpp = (const struct icmp *) data;
     768                 :          0 :                 RecordVal* icmp_hdr = new RecordVal(icmp_hdr_type);
     769                 :            : 
     770                 :          0 :                 icmp_hdr->Assign(0, new Val(icmpp->icmp_type, TYPE_COUNT));
     771                 :            : 
     772                 :          0 :                 pkt_hdr->Assign(3, icmp_hdr);
     773                 :            :                 break;
     774                 :            :                 }
     775                 :            : 
     776                 :            :         default:
     777                 :            :                 {
     778                 :            :                 // This is not a protocol we understand.
     779                 :            :                 }
     780                 :            :         }
     781                 :            : 
     782                 :          0 :         return pkt_hdr;
     783                 :            :         }
     784                 :            : 
     785                 :            : FragReassembler* NetSessions::NextFragment(double t, const IP_Hdr* ip,
     786                 :          0 :                                         const u_char* pkt, uint32 frag_field)
     787                 :            :         {
     788                 :          0 :         uint32 src_addr = uint32(ip->SrcAddr4());
     789                 :          0 :         uint32 dst_addr = uint32(ip->DstAddr4());
     790                 :          0 :         uint32 frag_id = ntohs(ip->ID4());   // we actually could skip conv.
     791                 :            : 
     792                 :          0 :         ListVal* key = new ListVal(TYPE_ANY);
     793                 :          0 :         key->Append(new Val(src_addr, TYPE_COUNT));
     794                 :          0 :         key->Append(new Val(dst_addr, TYPE_COUNT));
     795                 :          0 :         key->Append(new Val(frag_id, TYPE_COUNT));
     796                 :            : 
     797                 :          0 :         HashKey* h = ch->ComputeHash(key, 1);
     798         [ #  # ]:          0 :         if ( ! h )
     799                 :          0 :                 internal_error("hash computation failed");
     800                 :            : 
     801                 :          0 :         FragReassembler* f = fragments.Lookup(h);
     802         [ #  # ]:          0 :         if ( ! f )
     803                 :            :                 {
     804                 :          0 :                 f = new FragReassembler(this, ip, pkt, frag_field, h, t);
     805                 :          0 :                 fragments.Insert(h, f);
     806                 :          0 :                 Unref(key);
     807                 :          0 :                 return f;
     808                 :            :                 }
     809                 :            : 
     810         [ #  # ]:          0 :         delete h;
     811                 :          0 :         Unref(key);
     812                 :            : 
     813                 :          0 :         f->AddFragment(t, ip, pkt, frag_field);
     814                 :          0 :         return f;
     815                 :            :         }
     816                 :            : 
     817                 :            : int NetSessions::Get_OS_From_SYN(struct os_type* retval,
     818                 :            :                   uint16 tot, uint8 DF_flag, uint8 TTL, uint16 WSS,
     819                 :            :                   uint8 ocnt, uint8* op, uint16 MSS, uint8 win_scale,
     820                 :            :                   uint32 tstamp, /* uint8 TOS, */ uint32 quirks,
     821                 :          0 :                   uint8 ECN) const
     822                 :            :         {
     823                 :            :         return SYN_OS_Fingerprinter ?
     824                 :            :                 SYN_OS_Fingerprinter->FindMatch(retval, tot, DF_flag, TTL,
     825                 :            :                                 WSS, ocnt, op, MSS, win_scale, tstamp,
     826         [ #  # ]:          0 :                                 quirks, ECN) : 0;
     827                 :            :         }
     828                 :            : 
     829                 :          0 : bool NetSessions::CompareWithPreviousOSMatch(uint32 addr, int id) const
     830                 :            :         {
     831                 :            :         return SYN_OS_Fingerprinter ?
     832         [ #  # ]:          0 :                 SYN_OS_Fingerprinter->CacheMatch(addr, id) : 0;
     833                 :            :         }
     834                 :            : 
     835                 :          8 : Connection* NetSessions::FindConnection(Val* v)
     836                 :            :         {
     837                 :          8 :         BroType* vt = v->Type();
     838   [ -  +  #  # ]:          8 :         if ( ! IsRecord(vt->Tag()) )
                 [ -  + ]
     839                 :          0 :                 return 0;
     840                 :            : 
     841                 :          8 :         RecordType* vr = vt->AsRecordType();
     842                 :          8 :         const val_list* vl = v->AsRecord();
     843                 :            : 
     844                 :            :         int orig_h, orig_p;     // indices into record's value list
     845                 :            :         int resp_h, resp_p;
     846                 :            : 
     847         [ +  - ]:          8 :         if ( vr == conn_id )
     848                 :            :                 {
     849                 :          8 :                 orig_h = 0;
     850                 :          8 :                 orig_p = 1;
     851                 :          8 :                 resp_h = 2;
     852                 :          8 :                 resp_p = 3;
     853                 :            :                 }
     854                 :            : 
     855                 :            :         else
     856                 :            :                 {
     857                 :            :                 // While it's not a conn_id, it may have equivalent fields.
     858                 :          0 :                 orig_h = vr->FieldOffset("orig_h");
     859                 :          0 :                 resp_h = vr->FieldOffset("resp_h");
     860                 :          0 :                 orig_p = vr->FieldOffset("orig_p");
     861                 :          0 :                 resp_p = vr->FieldOffset("resp_p");
     862                 :            : 
     863   [ #  #  #  # ]:          0 :                 if ( orig_h < 0 || resp_h < 0 || orig_p < 0 || resp_p < 0 )
         [ #  # ][ #  # ]
     864                 :          0 :                         return 0;
     865                 :            : 
     866                 :            :                 // ### we ought to check that the fields have the right
     867                 :            :                 // types, too.
     868                 :            :                 }
     869                 :            : 
     870                 :          8 :         addr_type orig_addr = (*vl)[orig_h]->AsAddr();
     871                 :          8 :         addr_type resp_addr = (*vl)[resp_h]->AsAddr();
     872                 :            : 
     873                 :          8 :         PortVal* orig_portv = (*vl)[orig_p]->AsPortVal();
     874                 :          8 :         PortVal* resp_portv = (*vl)[resp_p]->AsPortVal();
     875                 :            : 
     876                 :            :         ConnID id;
     877                 :            : 
     878                 :            : #ifdef BROv6
     879                 :            :         id.src_addr = orig_addr;
     880                 :            :         id.dst_addr = resp_addr;
     881                 :            : #else
     882                 :          8 :         id.src_addr = &orig_addr;
     883                 :          8 :         id.dst_addr = &resp_addr;
     884                 :            : #endif
     885                 :            : 
     886                 :          8 :         id.src_port = htons((unsigned short) orig_portv->Port());
     887                 :          8 :         id.dst_port = htons((unsigned short) resp_portv->Port());
     888                 :            : 
     889                 :          8 :         id.is_one_way = 0;      // ### incorrect for ICMP connections
     890                 :            : 
     891                 :          8 :         HashKey* h = id.BuildConnKey();
     892         [ -  + ]:          8 :         if ( ! h )
     893                 :          0 :                 internal_error("hash computation failed");
     894                 :            : 
     895                 :            :         Dictionary* d;
     896                 :            : 
     897         [ +  - ]:          8 :         if ( orig_portv->IsTCP() )
     898                 :            :                 {
     899         [ +  - ]:          8 :                 if ( use_connection_compressor )
     900                 :            :                         {
     901                 :          8 :                         Connection* conn = conn_compressor->Lookup(h);
     902         [ +  - ]:          8 :                         delete h;
     903                 :          8 :                         return conn;
     904                 :            :                         }
     905                 :            :                 else
     906                 :          0 :                         d = &tcp_conns;
     907                 :            :                 }
     908         [ #  # ]:          0 :         else if ( orig_portv->IsUDP() )
     909                 :          0 :                 d = &udp_conns;
     910         [ #  # ]:          0 :         else if ( orig_portv->IsICMP() )
     911                 :          0 :                 d = &icmp_conns;
     912                 :            :         else
     913                 :            :                 {
     914                 :            :                 // This can happen due to pseudo-connections we
     915                 :            :                 // construct, for example for packet headers embedded
     916                 :            :                 // in ICMPs.
     917         [ #  # ]:          0 :                 delete h;
     918                 :          0 :                 return 0;
     919                 :            :                 }
     920                 :            : 
     921                 :          0 :         Connection* conn = (Connection*) d->Lookup(h);
     922                 :            : 
     923         [ #  # ]:          0 :         delete h;
     924                 :            : 
     925                 :          8 :         return conn;
     926                 :            :         }
     927                 :            : 
     928                 :       1624 : void NetSessions::Remove(Connection* c)
     929                 :            :         {
     930                 :       1624 :         HashKey* k = c->Key();
     931         [ +  - ]:       1624 :         if ( k )
     932                 :            :                 {
     933                 :       1624 :                 c->CancelTimers();
     934                 :            : 
     935                 :       1624 :                 TCP_Analyzer* ta = (TCP_Analyzer*) c->GetRootAnalyzer();
     936   [ +  -  +  + ]:       1624 :                 if ( ta && c->ConnTransport() == TRANSPORT_TCP )
                 [ +  + ]
     937                 :            :                         {
     938         [ -  + ]:        938 :                         assert(ta->GetTag() == AnalyzerTag::TCP);
     939                 :        938 :                         TCP_Endpoint* to = ta->Orig();
     940                 :        938 :                         TCP_Endpoint* tr = ta->Resp();
     941                 :            : 
     942                 :        938 :                         tcp_stats.StateLeft(to->state, tr->state);
     943                 :            :                         }
     944                 :            : 
     945         [ -  + ]:       1624 :                 if ( c->IsPersistent() )
     946                 :          0 :                         persistence_serializer->Unregister(c);
     947                 :            : 
     948                 :       1624 :                 c->Done();
     949                 :            : 
     950         [ +  - ]:       1624 :                 if ( connection_state_remove )
     951                 :       1624 :                         c->Event(connection_state_remove, 0);
     952                 :            : 
     953                 :            :                 // Zero out c's copy of the key, so that if c has been Ref()'d
     954                 :            :                 // up, we know on a future call to Remove() that it's no
     955                 :            :                 // longer in the dictionary.
     956                 :       1624 :                 c->ClearKey();
     957                 :            : 
     958   [ +  +  +  -  :       1624 :                 switch ( c->ConnTransport() ) {
                      - ]
     959                 :            :                 case TRANSPORT_TCP:
     960 [ +  - ][ +  - ]:        938 :                         if ( use_connection_compressor &&
                 [ -  + ]
     961                 :            :                              conn_compressor->Remove(k) )
     962                 :            :                                 // Note, if the Remove() returned false
     963                 :            :                                 // then the compressor doesn't know about
     964                 :            :                                 // this connection, which *should* mean that
     965                 :            :                                 // we never gave it the connection in the
     966                 :            :                                 // first place, and thus we should check
     967                 :            :                                 // the regular TCP table instead.
     968                 :            :                                 ;
     969                 :            : 
     970         [ #  # ]:          0 :                         else if ( ! tcp_conns.RemoveEntry(k) )
     971                 :          0 :                                 internal_error("connection missing");
     972                 :        938 :                         break;
     973                 :            : 
     974                 :            :                 case TRANSPORT_UDP:
     975         [ -  + ]:        681 :                         if ( ! udp_conns.RemoveEntry(k) )
     976                 :          0 :                                 internal_error("connection missing");
     977                 :        681 :                         break;
     978                 :            : 
     979                 :            :                 case TRANSPORT_ICMP:
     980         [ -  + ]:          5 :                         if ( ! icmp_conns.RemoveEntry(k) )
     981                 :          0 :                                 internal_error("connection missing");
     982                 :          5 :                         break;
     983                 :            : 
     984                 :            :                 case TRANSPORT_UNKNOWN:
     985                 :          0 :                         internal_error("unknown transport when removing connection");
     986                 :            :                         break;
     987                 :            :                 }
     988                 :            : 
     989                 :       1624 :                 Unref(c);
     990         [ +  - ]:       1624 :                 delete k;
     991                 :            :                 }
     992                 :       1624 :         }
     993                 :            : 
     994                 :          0 : void NetSessions::Remove(FragReassembler* f)
     995                 :            :         {
     996                 :          0 :         HashKey* k = f->Key();
     997         [ #  # ]:          0 :         if ( ! k )
     998                 :          0 :                 internal_error("fragment block not in dictionary");
     999                 :            : 
    1000         [ #  # ]:          0 :         if ( ! fragments.RemoveEntry(k) )
    1001                 :          0 :                 internal_error("fragment block missing");
    1002                 :            : 
    1003                 :          0 :         Unref(f);
    1004                 :          0 :         }
    1005                 :            : 
    1006                 :          0 : void NetSessions::Insert(Connection* c)
    1007                 :            :         {
    1008         [ #  # ]:          0 :         assert(c->Key());
    1009                 :            : 
    1010                 :          0 :         Connection* old = 0;
    1011                 :            : 
    1012   [ #  #  #  # ]:          0 :         switch ( c->ConnTransport() ) {
    1013                 :            :         // Remove first. Otherwise the dictioanry would still
    1014                 :            :         // reference the old key for already existing connections.
    1015                 :            : 
    1016                 :            :         case TRANSPORT_TCP:
    1017         [ #  # ]:          0 :                 if ( use_connection_compressor )
    1018                 :          0 :                         old = conn_compressor->Insert(c);
    1019                 :            :                 else
    1020                 :            :                         {
    1021                 :          0 :                         old = (Connection*) tcp_conns.Remove(c->Key());
    1022                 :          0 :                         tcp_conns.Insert(c->Key(), c);
    1023                 :            :                         }
    1024                 :          0 :                 break;
    1025                 :            : 
    1026                 :            :         case TRANSPORT_UDP:
    1027                 :          0 :                 old = (Connection*) udp_conns.Remove(c->Key());
    1028                 :          0 :                 udp_conns.Insert(c->Key(), c);
    1029                 :          0 :                 break;
    1030                 :            : 
    1031                 :            :         case TRANSPORT_ICMP:
    1032                 :          0 :                 old = (Connection*) icmp_conns.Remove(c->Key());
    1033                 :          0 :                 icmp_conns.Insert(c->Key(), c);
    1034                 :          0 :                 break;
    1035                 :            : 
    1036                 :            :         default:
    1037                 :          0 :                 internal_error("unknown connection type");
    1038                 :            :         }
    1039                 :            : 
    1040 [ #  # ][ #  # ]:          0 :         if ( old && old != c )
    1041                 :            :                 {
    1042                 :            :                 // Some clean-ups similar to those in Remove() (but invisible
    1043                 :            :                 // to the script layer).
    1044                 :          0 :                 old->CancelTimers();
    1045         [ #  # ]:          0 :                 if ( old->IsPersistent() )
    1046                 :          0 :                         persistence_serializer->Unregister(old);
    1047         [ #  # ]:          0 :                 delete old->Key();
    1048                 :          0 :                 old->ClearKey();
    1049                 :          0 :                 Unref(old);
    1050                 :            :                 }
    1051                 :          0 :         }
    1052                 :            : 
    1053                 :          1 : void NetSessions::Drain()
    1054                 :            :         {
    1055         [ +  - ]:          1 :         if ( use_connection_compressor )
    1056                 :          1 :                 conn_compressor->Drain();
    1057                 :            : 
    1058                 :          1 :         IterCookie* cookie = tcp_conns.InitForIteration();
    1059                 :            :         Connection* tc;
    1060                 :            : 
    1061         [ -  + ]:          1 :         while ( (tc = tcp_conns.NextEntry(cookie)) )
    1062                 :            :                 {
    1063                 :          0 :                 tc->Done();
    1064                 :          0 :                 tc->Event(connection_state_remove, 0);
    1065                 :            :                 }
    1066                 :            : 
    1067                 :          1 :         cookie = udp_conns.InitForIteration();
    1068                 :            :         Connection* uc;
    1069                 :            : 
    1070         [ +  + ]:          4 :         while ( (uc = udp_conns.NextEntry(cookie)) )
    1071                 :            :                 {
    1072                 :          3 :                 uc->Done();
    1073                 :          3 :                 uc->Event(connection_state_remove, 0);
    1074                 :            :                 }
    1075                 :            : 
    1076                 :          1 :         cookie = icmp_conns.InitForIteration();
    1077                 :            :         Connection* ic;
    1078                 :            : 
    1079         [ -  + ]:          1 :         while ( (ic = icmp_conns.NextEntry(cookie)) )
    1080                 :            :                 {
    1081                 :          0 :                 ic->Done();
    1082                 :          0 :                 ic->Event(connection_state_remove, 0);
    1083                 :            :                 }
    1084                 :            : 
    1085                 :          1 :         ExpireTimerMgrs();
    1086                 :          1 :         }
    1087                 :            : 
    1088                 :          0 : void NetSessions::HeartBeat(double t)
    1089                 :            :         {
    1090                 :          0 :         unsigned int recv = 0;
    1091                 :          0 :         unsigned int drop = 0;
    1092                 :          0 :         unsigned int link = 0;
    1093                 :            : 
    1094         [ #  # ]:          0 :         loop_over_list(pkt_srcs, i)
    1095                 :            :                 {
    1096                 :          0 :                 PktSrc* ps = pkt_srcs[i];
    1097                 :            : 
    1098                 :            :                 struct PktSrc::Stats stat;
    1099                 :          0 :                 ps->Statistics(&stat);
    1100                 :          0 :                 recv += stat.received;
    1101                 :          0 :                 drop += stat.dropped;
    1102                 :          0 :                 link += stat.link;
    1103                 :            :                 }
    1104                 :            : 
    1105                 :          0 :         val_list* vl = new val_list;
    1106                 :            : 
    1107                 :          0 :         vl->append(new Val(t, TYPE_TIME));
    1108                 :            : 
    1109                 :          0 :         RecordVal* ns = new RecordVal(net_stats);
    1110                 :          0 :         ns->Assign(0, new Val(recv, TYPE_COUNT));
    1111                 :          0 :         ns->Assign(1, new Val(drop, TYPE_COUNT));
    1112                 :          0 :         ns->Assign(2, new Val(link, TYPE_COUNT));
    1113                 :            : 
    1114                 :          0 :         vl->append(ns);
    1115                 :            : 
    1116                 :          0 :         mgr.QueueEvent(net_stats_update, vl);
    1117                 :            : 
    1118                 :          0 :         timer_mgr->Add(new NetworkTimer(this, t + heartbeat_interval));
    1119                 :          0 :         }
    1120                 :            : 
    1121                 :          0 : void NetSessions::GetStats(SessionStats& s) const
    1122                 :            :         {
    1123                 :          0 :         s.num_TCP_conns = tcp_conns.Length();
    1124                 :          0 :         s.num_UDP_conns = udp_conns.Length();
    1125                 :          0 :         s.num_ICMP_conns = icmp_conns.Length();
    1126                 :          0 :         s.num_fragments = fragments.Length();
    1127                 :          0 :         s.num_packets = num_packets_processed;
    1128                 :          0 :         s.num_timers = timer_mgr->Size();
    1129                 :          0 :         s.num_events_queued = num_events_queued;
    1130                 :          0 :         s.num_events_dispatched = num_events_dispatched;
    1131                 :            : 
    1132                 :          0 :         s.max_TCP_conns = tcp_conns.MaxLength();
    1133                 :          0 :         s.max_UDP_conns = udp_conns.MaxLength();
    1134                 :          0 :         s.max_ICMP_conns = icmp_conns.MaxLength();
    1135                 :          0 :         s.max_fragments = fragments.MaxLength();
    1136                 :          0 :         s.max_timers = timer_mgr->PeakSize();
    1137                 :          0 :         }
    1138                 :            : 
    1139                 :            : Connection* NetSessions::NewConn(HashKey* k, double t, const ConnID* id,
    1140                 :       1627 :                                         const u_char* data, int proto)
    1141                 :            :         {
    1142                 :            :         // FIXME: This should be cleaned up a bit, it's too protocol-specific.
    1143                 :            :         // But I'm not yet sure what the right abstraction for these things is.
    1144                 :       1627 :         int src_h = ntohs(id->src_port);
    1145                 :       1627 :         int dst_h = ntohs(id->dst_port);
    1146                 :       1627 :         int flags = 0;
    1147                 :            : 
    1148                 :            :         // Hmm... This is not great.
    1149                 :            :         TransportProto tproto;
    1150   [ +  +  +  - ]:       1627 :         switch ( proto ) {
    1151                 :            :                 case IPPROTO_ICMP:
    1152                 :          5 :                         tproto = TRANSPORT_ICMP;
    1153                 :          5 :                         break;
    1154                 :            :                 case IPPROTO_TCP:
    1155                 :        938 :                         tproto = TRANSPORT_TCP;
    1156                 :        938 :                         break;
    1157                 :            :                 case IPPROTO_UDP:
    1158                 :        684 :                         tproto = TRANSPORT_UDP;
    1159                 :        684 :                         break;
    1160                 :            :                 default:
    1161                 :          0 :                         internal_error("unknown transport protocol");
    1162                 :            :                         break;
    1163                 :            :         };
    1164                 :            : 
    1165         [ +  + ]:       1627 :         if ( tproto == TRANSPORT_TCP )
    1166                 :            :                 {
    1167                 :        938 :                 const struct tcphdr* tp = (const struct tcphdr*) data;
    1168                 :        938 :                 flags = tp->th_flags;
    1169                 :            :                 }
    1170                 :            : 
    1171                 :       1627 :         bool flip = false;
    1172                 :            : 
    1173         [ -  + ]:       1627 :         if ( ! WantConnection(src_h, dst_h, tproto, flags, flip) )
    1174                 :          0 :                 return 0;
    1175                 :            : 
    1176         [ +  + ]:       1627 :         if ( flip )
    1177                 :            :                 {
    1178                 :            :                 // Make a guess that we're seeing the tail half of
    1179                 :            :                 // an analyzable connection.
    1180                 :        387 :                 ConnID flip_id = *id;
    1181                 :            : 
    1182                 :        387 :                 const uint32* ta = flip_id.src_addr;
    1183                 :        387 :                 flip_id.src_addr = flip_id.dst_addr;
    1184                 :        387 :                 flip_id.dst_addr = ta;
    1185                 :            : 
    1186                 :        387 :                 uint32 t = flip_id.src_port;
    1187                 :        387 :                 flip_id.src_port = flip_id.dst_port;
    1188                 :        387 :                 flip_id.dst_port = t;
    1189                 :            : 
    1190                 :        387 :                 id = &flip_id;
    1191                 :            :                 }
    1192                 :            : 
    1193                 :       1627 :         Connection* conn = new Connection(this, k, t, id);
    1194                 :       1627 :         conn->SetTransport(tproto);
    1195                 :       1627 :         dpm->BuildInitialAnalyzerTree(tproto, conn, data);
    1196                 :            : 
    1197                 :       1627 :         bool external = conn->IsExternal();
    1198                 :            : 
    1199         [ -  + ]:       1627 :         if ( external )
    1200                 :            :                 conn->AppendAddl(fmt("tag=%s",
    1201                 :          0 :                                         conn->GetTimerMgr()->GetTag().c_str()));
    1202                 :            : 
    1203                 :            :         // If the connection compressor is active, it takes care of the
    1204                 :            :         // new_connection/connection_external events for TCP connections.
    1205 [ +  - ][ +  + ]:       1627 :         if ( new_connection &&
         [ -  + ][ +  + ]
    1206                 :            :              (tproto != TRANSPORT_TCP || ! use_connection_compressor) )
    1207                 :            :                 {
    1208                 :        689 :                 conn->Event(new_connection, 0);
    1209                 :            : 
    1210         [ -  + ]:        689 :                 if ( external )
    1211                 :            :                         {
    1212                 :          0 :                         val_list* vl = new val_list(2);
    1213                 :          0 :                         vl->append(conn->BuildConnVal());
    1214                 :          0 :                         vl->append(new StringVal(conn->GetTimerMgr()->GetTag().c_str()));
    1215                 :          0 :                         conn->ConnectionEvent(connection_external, 0, vl);
    1216                 :            :                         }
    1217                 :            :                 }
    1218                 :            : 
    1219                 :       1627 :         return conn;
    1220                 :            :         }
    1221                 :            : 
    1222                 :       1880 : bool NetSessions::IsLikelyServerPort(uint32 port, TransportProto proto) const
    1223                 :            :         {
    1224                 :            :         // We keep a cached in-core version of the table to speed up the lookup.
    1225 [ +  + ][ +  - ]:       1881 :         static set<bro_uint_t> port_cache;
                 [ #  # ]
    1226                 :            :         static bool have_cache = false;
    1227                 :            : 
    1228         [ +  + ]:       1880 :         if ( ! have_cache )
    1229                 :            :                 {
    1230                 :          1 :                 ListVal* lv = likely_server_ports->ConvertToPureList();
    1231         [ +  + ]:         55 :                 for ( int i = 0; i < lv->Length(); i++ )
    1232                 :         54 :                         port_cache.insert(lv->Index(i)->InternalUnsigned());
    1233                 :          1 :                 have_cache = true;
    1234                 :          1 :                 Unref(lv);
    1235                 :            :                 }
    1236                 :            : 
    1237                 :            :         // We exploit our knowledge of PortVal's internal storage mechanism
    1238                 :            :         // here.
    1239         [ +  + ]:       1880 :         if ( proto == TRANSPORT_TCP )
    1240                 :       1063 :                 port |= TCP_PORT_MASK;
    1241         [ +  - ]:        817 :         else if ( proto == TRANSPORT_UDP )
    1242                 :        817 :                 port |= UDP_PORT_MASK;
    1243         [ #  # ]:          0 :         else if ( proto == TRANSPORT_ICMP )
    1244                 :          0 :                 port |= ICMP_PORT_MASK;
    1245                 :            : 
    1246                 :       1880 :         return port_cache.find(port) != port_cache.end();
    1247                 :            :         }
    1248                 :            : 
    1249                 :            : bool NetSessions::WantConnection(uint16 src_port, uint16 dst_port,
    1250                 :            :                                         TransportProto transport_proto,
    1251                 :       2317 :                                         uint8 tcp_flags, bool& flip_roles)
    1252                 :            :         {
    1253                 :       2317 :         flip_roles = false;
    1254                 :            : 
    1255         [ +  + ]:       2317 :         if ( transport_proto == TRANSPORT_TCP )
    1256                 :            :                 {
    1257 [ +  + ][ +  + ]:       1628 :                 if ( ! (tcp_flags & TH_SYN) || (tcp_flags & TH_ACK) )
    1258                 :            :                         {
    1259                 :            :                         // The new connection is starting either without a SYN,
    1260                 :            :                         // or with a SYN ack. This means it's a partial connection.
    1261         [ -  + ]:        632 :                         if ( ! partial_connection_ok )
    1262                 :          0 :                                 return false;
    1263                 :            : 
    1264 [ +  + ][ -  + ]:        632 :                         if ( tcp_flags & TH_SYN && ! tcp_SYN_ack_ok )
    1265                 :          0 :                                 return false;
    1266                 :            : 
    1267                 :            :                         // Try to guess true responder by the port numbers.
    1268                 :            :                         // (We might also think that for SYN acks we could
    1269                 :            :                         // safely flip the roles, but that doesn't work
    1270                 :            :                         // for stealth scans.)
    1271         [ +  + ]:        632 :                         if ( IsLikelyServerPort(src_port, TRANSPORT_TCP) )
    1272                 :            :                                 { // connection is a candidate for flipping
    1273         [ -  + ]:        431 :                                 if ( IsLikelyServerPort(dst_port, TRANSPORT_TCP) )
    1274                 :            :                                         // Hmmm, both source and destination
    1275                 :            :                                         // are plausible.  Heuristic: flip only
    1276                 :            :                                         // if (1) this isn't a SYN ACK (to avoid
    1277                 :            :                                         // confusing stealth scans) and
    1278                 :            :                                         // (2) dest port > src port (to favor
    1279                 :            :                                         // more plausible servers).
    1280 [ #  # ][ #  # ]:          0 :                                         flip_roles = ! (tcp_flags & TH_SYN) && src_port < dst_port;
    1281                 :            :                                 else
    1282                 :            :                                         // Source is plausible, destination isn't.
    1283                 :       1628 :                                         flip_roles = true;
    1284                 :            :                                 }
    1285                 :            :                         }
    1286                 :            :                 }
    1287                 :            : 
    1288         [ +  + ]:        689 :         else if ( transport_proto == TRANSPORT_UDP )
    1289                 :            :                 flip_roles =
    1290                 :            :                         IsLikelyServerPort(src_port, TRANSPORT_UDP) &&
    1291 [ +  + ][ +  + ]:        684 :                         ! IsLikelyServerPort(dst_port, TRANSPORT_UDP);
    1292                 :            : 
    1293                 :       2317 :         return true;
    1294                 :            :         }
    1295                 :            : 
    1296                 :      42694 : TimerMgr* NetSessions::LookupTimerMgr(const TimerMgr::Tag* tag, bool create)
    1297                 :            :         {
    1298         [ +  - ]:      42694 :         if ( ! tag )
    1299                 :            :                 {
    1300                 :      42694 :                 DBG_LOG(DBG_TM, "no tag, using global timer mgr %p", timer_mgr);
    1301                 :      42694 :                 return timer_mgr;
    1302                 :            :                 }
    1303                 :            : 
    1304                 :          0 :         TimerMgrMap::iterator i = timer_mgrs.find(*tag);
    1305         [ #  # ]:          0 :         if ( i != timer_mgrs.end() )
    1306                 :            :                 {
    1307                 :          0 :                 DBG_LOG(DBG_TM, "tag %s, using non-global timer mgr %p", tag->c_str(), i->second);
    1308                 :          0 :                 return i->second;
    1309                 :            :                 }
    1310                 :            :         else
    1311                 :            :                 {
    1312         [ #  # ]:          0 :                 if ( ! create )
    1313                 :          0 :                         return 0;
    1314                 :            : 
    1315                 :            :                 // Create new queue for tag.
    1316                 :          0 :                 TimerMgr* mgr = new CQ_TimerMgr(*tag);
    1317                 :          0 :                 DBG_LOG(DBG_TM, "tag %s, creating new non-global timer mgr %p", tag->c_str(), mgr);
    1318                 :      42694 :                 timer_mgrs.insert(TimerMgrMap::value_type(*tag, mgr));
    1319                 :          0 :                 double t = timer_mgr->Time() + timer_mgr_inactivity_timeout;
    1320                 :          0 :                 timer_mgr->Add(new TimerMgrExpireTimer(t, mgr));
    1321                 :          0 :                 return mgr;
    1322                 :            :                 }
    1323                 :            :         }
    1324                 :            : 
    1325                 :          1 : void NetSessions::ExpireTimerMgrs()
    1326                 :            :         {
    1327         [ -  + ]:          1 :         for ( TimerMgrMap::iterator i = timer_mgrs.begin();
    1328                 :            :               i != timer_mgrs.end(); ++i )
    1329                 :            :                 {
    1330                 :          0 :                 i->second->Expire();
    1331         [ #  # ]:          0 :                 delete i->second;
    1332                 :            :                 }
    1333                 :          1 :         }
    1334                 :            : 
    1335                 :            : void NetSessions::DumpPacket(const struct pcap_pkthdr* hdr,
    1336                 :      20378 :                                 const u_char* pkt, int len)
    1337                 :            :         {
    1338         [ +  - ]:      20378 :         if ( ! pkt_dumper )
    1339                 :      20378 :                 return;
    1340                 :            : 
    1341         [ #  # ]:          0 :         if ( len == 0 )
    1342                 :          0 :                 pkt_dumper->Dump(hdr, pkt);
    1343                 :            :         else
    1344                 :            :                 {
    1345                 :          0 :                 struct pcap_pkthdr h = *hdr;
    1346                 :          0 :                 h.caplen = len;
    1347         [ #  # ]:          0 :                 if ( h.caplen > hdr->caplen )
    1348                 :          0 :                         internal_error("bad modified caplen");
    1349                 :      20378 :                 pkt_dumper->Dump(&h, pkt);
    1350                 :            :                 }
    1351                 :            :         }
    1352                 :            : 
    1353                 :            : void NetSessions::Internal(const char* msg, const struct pcap_pkthdr* hdr,
    1354                 :          0 :                                 const u_char* pkt)
    1355                 :            :         {
    1356                 :          0 :         DumpPacket(hdr, pkt);
    1357                 :          0 :         internal_error(msg);
    1358                 :            :         }
    1359                 :            : 
    1360                 :            : void NetSessions::Weird(const char* name,
    1361                 :        969 :                         const struct pcap_pkthdr* hdr, const u_char* pkt)
    1362                 :            :         {
    1363         [ +  - ]:        969 :         if ( hdr )
    1364                 :        969 :                 dump_this_packet = 1;
    1365                 :            : 
    1366         [ +  - ]:        969 :         if ( net_weird )
    1367                 :            :                 {
    1368                 :        969 :                 val_list* vl = new val_list;
    1369                 :        969 :                 vl->append(new StringVal(name));
    1370                 :        969 :                 mgr.QueueEvent(net_weird, vl);
    1371                 :            :                 }
    1372                 :            :         else
    1373                 :          0 :                 fprintf(stderr, "weird: %.06f %s\n", network_time, name);
    1374                 :        969 :         }
    1375                 :            : 
    1376                 :          0 : void NetSessions::Weird(const char* name, const IP_Hdr* ip)
    1377                 :            :         {
    1378         [ #  # ]:          0 :         if ( flow_weird )
    1379                 :            :                 {
    1380                 :          0 :                 val_list* vl = new val_list;
    1381                 :          0 :                 vl->append(new StringVal(name));
    1382                 :          0 :                 vl->append(new AddrVal(ip->SrcAddr4()));
    1383                 :          0 :                 vl->append(new AddrVal(ip->DstAddr4()));
    1384                 :          0 :                 mgr.QueueEvent(flow_weird, vl);
    1385                 :            :                 }
    1386                 :            :         else
    1387                 :          0 :                 fprintf(stderr, "weird: %.06f %s\n", network_time, name);
    1388                 :          0 :         }
    1389                 :            : 
    1390                 :          0 : unsigned int NetSessions::ConnectionMemoryUsage()
    1391                 :            :         {
    1392                 :          0 :         unsigned int mem = 0;
    1393                 :            : 
    1394         [ #  # ]:          0 :         if ( terminating )
    1395                 :            :                 // Connections have been flushed already.
    1396                 :          0 :                 return 0;
    1397                 :            : 
    1398                 :          0 :         IterCookie* cookie = tcp_conns.InitForIteration();
    1399                 :            :         Connection* tc;
    1400                 :            : 
    1401         [ #  # ]:          0 :         while ( (tc = tcp_conns.NextEntry(cookie)) )
    1402                 :          0 :                 mem += tc->MemoryAllocation();
    1403                 :            : 
    1404                 :          0 :         cookie = udp_conns.InitForIteration();
    1405                 :            :         Connection* uc;
    1406                 :            : 
    1407         [ #  # ]:          0 :         while ( (uc = udp_conns.NextEntry(cookie)) )
    1408                 :          0 :                 mem += uc->MemoryAllocation();
    1409                 :            : 
    1410                 :          0 :         cookie = icmp_conns.InitForIteration();
    1411                 :            :         Connection* ic;
    1412                 :            : 
    1413         [ #  # ]:          0 :         while ( (ic = icmp_conns.NextEntry(cookie)) )
    1414                 :          0 :                 mem += ic->MemoryAllocation();
    1415                 :            : 
    1416                 :          0 :         return mem;
    1417                 :            :         }
    1418                 :            : 
    1419                 :          0 : unsigned int NetSessions::ConnectionMemoryUsageConnVals()
    1420                 :            :         {
    1421                 :          0 :         unsigned int mem = 0;
    1422                 :            : 
    1423         [ #  # ]:          0 :         if ( terminating )
    1424                 :            :                 // Connections have been flushed already.
    1425                 :          0 :                 return 0;
    1426                 :            : 
    1427                 :          0 :         IterCookie* cookie = tcp_conns.InitForIteration();
    1428                 :            :         Connection* tc;
    1429                 :            : 
    1430         [ #  # ]:          0 :         while ( (tc = tcp_conns.NextEntry(cookie)) )
    1431                 :          0 :                 mem += tc->MemoryAllocationConnVal();
    1432                 :            : 
    1433                 :          0 :         cookie = udp_conns.InitForIteration();
    1434                 :            :         Connection* uc;
    1435                 :            : 
    1436         [ #  # ]:          0 :         while ( (uc = udp_conns.NextEntry(cookie)) )
    1437                 :          0 :                 mem += uc->MemoryAllocationConnVal();
    1438                 :            : 
    1439                 :          0 :         cookie = icmp_conns.InitForIteration();
    1440                 :            :         Connection* ic;
    1441                 :            : 
    1442         [ #  # ]:          0 :         while ( (ic = icmp_conns.NextEntry(cookie)) )
    1443                 :          0 :                 mem += ic->MemoryAllocationConnVal();
    1444                 :            : 
    1445                 :          0 :         return mem;
    1446                 :            :         }
    1447                 :            : 
    1448                 :          0 : unsigned int NetSessions::MemoryAllocation()
    1449                 :            :         {
    1450         [ #  # ]:          0 :         if ( terminating )
    1451                 :            :                 // Connections have been flushed already.
    1452                 :          0 :                 return 0;
    1453                 :            : 
    1454                 :            :         return ConnectionMemoryUsage()
    1455                 :            :                 + padded_sizeof(*this)
    1456                 :            :                 + ch->MemoryAllocation()
    1457                 :            :                 // must take care we don't count the HaskKeys twice.
    1458                 :            :                 + tcp_conns.MemoryAllocation() - padded_sizeof(tcp_conns) -
    1459                 :            :                 // 12 is sizeof(Key) from ConnID::BuildConnKey();
    1460                 :            :                 // it can't be (easily) accessed here. :-(
    1461                 :            :                         (tcp_conns.Length() * pad_size(12))
    1462                 :            :                 + udp_conns.MemoryAllocation() - padded_sizeof(udp_conns) -
    1463                 :            :                         (udp_conns.Length() * pad_size(12))
    1464                 :            :                 + icmp_conns.MemoryAllocation() - padded_sizeof(icmp_conns) -
    1465                 :            :                         (icmp_conns.Length() * pad_size(12))
    1466                 :          0 :                 + fragments.MemoryAllocation() - padded_sizeof(fragments)
    1467                 :            :                 // FIXME: MemoryAllocation() not implemented for rest.
    1468                 :            :                 ;
    1469 [ +  - ][ +  - ]:          6 :         }

Generated by: LCOV version 1.8