LCOV - code coverage report
Current view: top level - src - net_util.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 62 103 60.2 %
Date: 2010-12-13 Functions: 10 15 66.7 %
Branches: 22 52 42.3 %

           Branch data     Line data    Source code
       1                 :            : // $Id: net_util.cc 6219 2008-10-01 05:39:07Z vern $
       2                 :            : //
       3                 :            : // See the file "COPYING" in the main distribution directory for copyright.
       4                 :            : 
       5                 :            : #include "config.h"
       6                 :            : 
       7                 :            : #ifdef BROv6
       8                 :            : #include <sys/types.h>
       9                 :            : #include <sys/socket.h>
      10                 :            : 
      11                 :            : #include <netinet/in.h>
      12                 :            : 
      13                 :            : #include <arpa/inet.h>
      14                 :            : #endif
      15                 :            : 
      16                 :            : #include "net_util.h"
      17                 :            : 
      18                 :            : // - adapted from tcpdump
      19                 :            : // Returns the ones-complement checksum of a chunk of b short-aligned bytes.
      20                 :      50965 : int ones_complement_checksum(const void* p, int b, uint32 sum)
      21                 :            :         {
      22                 :      50965 :         const u_short* sp = (u_short*) p;       // better be aligned!
      23                 :            : 
      24                 :      50965 :         b /= 2; // convert to count of short's
      25                 :            : 
      26                 :            :         /* No need for endian conversions. */
      27         [ +  + ]:    5210027 :         while ( --b >= 0 )
      28                 :    5159062 :                 sum += *sp++;
      29                 :            : 
      30         [ +  + ]:      96381 :         while ( sum > 0xffff )
      31                 :      45416 :                 sum = (sum & 0xffff) + (sum >> 16);
      32                 :            : 
      33                 :      50965 :         return sum;
      34                 :            :         }
      35                 :            : 
      36                 :        524 : int tcp_checksum(const struct ip* ip, const struct tcphdr* tp, int len)
      37                 :            :         {
      38                 :            :         // ### Note, this is only correct for IPv4.  This routine is only
      39                 :            :         // used by the connection compressor (which we turn off for IPv6
      40                 :            :         // traffic) and trace rewriting (which currently doesn't support
      41                 :            :         // IPv6 either).
      42                 :            : 
      43                 :        524 :         int tcp_len = tp->th_off * 4 + len;
      44                 :            :         uint32 sum;
      45                 :            : 
      46         [ -  + ]:        524 :         if ( len % 2 == 1 )
      47                 :            :                 // Add in pad byte.
      48                 :          0 :                 sum = htons(((const u_char*) tp)[tcp_len - 1] << 8);
      49                 :            :         else
      50                 :        524 :                 sum = 0;
      51                 :            : 
      52                 :        524 :         sum = ones_complement_checksum((void*) &ip->ip_src.s_addr, 4, sum);
      53                 :        524 :         sum = ones_complement_checksum((void*) &ip->ip_dst.s_addr, 4, sum);
      54                 :            : 
      55                 :            :         uint32 addl_pseudo =
      56                 :        524 :                 (htons(IPPROTO_TCP) << 16) | htons((unsigned short) tcp_len);
      57                 :            : 
      58                 :        524 :         sum = ones_complement_checksum((void*) &addl_pseudo, 4, sum);
      59                 :        524 :         sum = ones_complement_checksum((void*) tp, tcp_len, sum);
      60                 :            : 
      61                 :        524 :         return sum;
      62                 :            :         }
      63                 :            : 
      64                 :       1683 : int udp_checksum(const struct ip* ip, const struct udphdr* up, int len)
      65                 :            :         {
      66                 :            :         uint32 sum;
      67                 :            : 
      68         [ +  + ]:       1683 :         if ( len % 2 == 1 )
      69                 :            :                 // Add in pad byte.
      70                 :        511 :                 sum = htons(((const u_char*) up)[len - 1] << 8);
      71                 :            :         else
      72                 :       1172 :                 sum = 0;
      73                 :            : 
      74                 :       1683 :         sum = ones_complement_checksum((void*) &ip->ip_src.s_addr, 4, sum);
      75                 :       1683 :         sum = ones_complement_checksum((void*) &ip->ip_dst.s_addr, 4, sum);
      76                 :            : 
      77                 :            :         uint32 addl_pseudo =
      78                 :       1683 :                 (htons(IPPROTO_UDP) << 16) | htons((unsigned short) len);
      79                 :            : 
      80                 :       1683 :         sum = ones_complement_checksum((void*) &addl_pseudo, 4, sum);
      81                 :       1683 :         sum = ones_complement_checksum((void*) up, len, sum);
      82                 :            : 
      83                 :       1683 :         return sum;
      84                 :            :         }
      85                 :            : 
      86                 :            : #ifdef BROv6
      87                 :            : int udp6_checksum(const struct ip6_hdr* ip6, const struct udphdr* up, int len)
      88                 :            :         {
      89                 :            :         uint32 sum;
      90                 :            : 
      91                 :            :         if ( len % 2 == 1 )
      92                 :            :                 // Add in pad byte.
      93                 :            :                 sum = htons(((const u_char*) up)[len - 1] << 8);
      94                 :            :         else
      95                 :            :                 sum = 0;
      96                 :            : 
      97                 :            :         sum = ones_complement_checksum((void*) ip6->ip6_src.s6_addr, 16, sum);
      98                 :            :         sum = ones_complement_checksum((void*) ip6->ip6_dst.s6_addr, 16, sum);
      99                 :            : 
     100                 :            :         sum = ones_complement_checksum((void*) &len, 4, sum);
     101                 :            :         uint32 addl_pseudo = htons(IPPROTO_UDP);
     102                 :            :         sum = ones_complement_checksum((void*) &addl_pseudo, 4, sum);
     103                 :            :         sum = ones_complement_checksum((void*) up, len, sum);
     104                 :            : 
     105                 :            :         return sum;
     106                 :            :         }
     107                 :            : #endif
     108                 :            : 
     109                 :         31 : int icmp_checksum(const struct icmp* icmpp, int len)
     110                 :            :         {
     111                 :            :         uint32 sum;
     112                 :            : 
     113         [ +  + ]:         31 :         if ( len % 2 == 1 )
     114                 :            :                 // Add in pad byte.
     115                 :          1 :                 sum = htons(((const u_char*) icmpp)[len - 1] << 8);
     116                 :            :         else
     117                 :         30 :                 sum = 0;
     118                 :            : 
     119                 :         31 :         sum = ones_complement_checksum((void*) icmpp, len, sum);
     120                 :            : 
     121                 :         31 :         return sum;
     122                 :            :         }
     123                 :            : 
     124                 :            : 
     125                 :            : #define CLASS_A 0x00000000
     126                 :            : #define CLASS_B 0x80000000
     127                 :            : #define CLASS_C 0xc0000000
     128                 :            : #define CLASS_D 0xe0000000
     129                 :            : #define CLASS_E 0xf0000000
     130                 :            : 
     131                 :            : #define CHECK_CLASS(addr,class) (((addr) & (class)) == (class))
     132                 :          0 : char addr_to_class(uint32 addr)
     133                 :            :         {
     134         [ #  # ]:          0 :         if ( CHECK_CLASS(addr, CLASS_E) )
     135                 :          0 :                 return 'E';
     136         [ #  # ]:          0 :         else if ( CHECK_CLASS(addr, CLASS_D) )
     137                 :          0 :                 return 'D';
     138         [ #  # ]:          0 :         else if ( CHECK_CLASS(addr, CLASS_C) )
     139                 :          0 :                 return 'C';
     140         [ #  # ]:          0 :         else if ( CHECK_CLASS(addr, CLASS_B) )
     141                 :          0 :                 return 'B';
     142                 :            :         else
     143                 :          0 :                 return 'A';
     144                 :            :         }
     145                 :            : 
     146                 :          0 : uint32 addr_to_net(uint32 addr)
     147                 :            :         {
     148         [ #  # ]:          0 :         if ( CHECK_CLASS(addr, CLASS_D) )
     149                 :            :                 ; // class D's are left alone ###
     150         [ #  # ]:          0 :         else if ( CHECK_CLASS(addr, CLASS_C) )
     151                 :          0 :                 addr = addr & 0xffffff00;
     152         [ #  # ]:          0 :         else if ( CHECK_CLASS(addr, CLASS_B) )
     153                 :          0 :                 addr = addr & 0xffff0000;
     154                 :            :         else
     155                 :          0 :                 addr = addr & 0xff000000;
     156                 :            : 
     157                 :          0 :         return addr;
     158                 :            :         }
     159                 :            : 
     160                 :      55146 : const char* dotted_addr(uint32 addr, int alternative)
     161                 :            :         {
     162                 :      55146 :         addr = ntohl(addr);
     163         [ -  + ]:      55146 :         const char* fmt = alternative ? "%d,%d.%d.%d" : "%d.%d.%d.%d";
     164                 :            : 
     165                 :            :         static char buf[32];
     166                 :            :         snprintf(buf, sizeof(buf), fmt,
     167                 :            :                 addr >> 24, (addr >> 16) & 0xff,
     168                 :      55146 :                 (addr >> 8) & 0xff, addr & 0xff);
     169                 :            : 
     170                 :      55146 :         return buf;
     171                 :            :         }
     172                 :            : 
     173                 :      45192 : const char* dotted_addr(const uint32* addr, int alternative)
     174                 :            :         {
     175                 :            : #ifdef BROv6
     176                 :            :         if ( is_v4_addr(addr) )
     177                 :            :                 return dotted_addr(addr[3], alternative);
     178                 :            : 
     179                 :            :         static char buf[256];
     180                 :            : 
     181                 :            :         if ( inet_ntop(AF_INET6, addr, buf, sizeof buf) == NULL )
     182                 :            :                 return "<bad IPv6 address conversion>";
     183                 :            : 
     184                 :            :         return buf;
     185                 :            : 
     186                 :            : #else
     187                 :      45192 :         return dotted_addr(to_v4_addr(addr), alternative);
     188                 :            : #endif
     189                 :            :         }
     190                 :            : 
     191                 :          0 : const char* dotted_net(uint32 addr)
     192                 :            :         {
     193                 :          0 :         addr = ntohl(addr);
     194                 :            : 
     195                 :            :         static char buf[32];
     196                 :            : 
     197         [ #  # ]:          0 :         if ( CHECK_CLASS(addr, CLASS_D) )
     198                 :            :                 sprintf(buf, "%d.%d.%d.%d",
     199                 :            :                         addr >> 24, (addr >> 16) & 0xff,
     200                 :          0 :                         (addr >> 8) & 0xff, addr & 0xff);
     201                 :            : 
     202         [ #  # ]:          0 :         else if ( CHECK_CLASS(addr, CLASS_C) )
     203                 :            :                 sprintf(buf, "%d.%d.%d",
     204                 :          0 :                         addr >> 24, (addr >> 16) & 0xff, (addr >> 8) & 0xff);
     205                 :            : 
     206                 :            :         else
     207                 :            :                 // Same for class A's and B's.
     208                 :          0 :                 sprintf(buf, "%d.%d", addr >> 24, (addr >> 16) & 0xff);
     209                 :            : 
     210                 :          0 :         return buf;
     211                 :            :         }
     212                 :            : 
     213                 :            : #ifdef BROv6
     214                 :            : const char* dotted_net6(const uint32* addr)
     215                 :            :         {
     216                 :            :         if ( is_v4_addr(addr) )
     217                 :            :                 return dotted_net(to_v4_addr(addr));
     218                 :            :         else
     219                 :            :                 // ### this isn't right, but net's should go away eventually ...
     220                 :            :                 return dotted_addr(addr);
     221                 :            :         }
     222                 :            : #endif
     223                 :            : 
     224                 :         43 : uint32 dotted_to_addr(const char* addr_text)
     225                 :            :         {
     226                 :            :         int addr[4];
     227                 :            : 
     228         [ -  + ]:         43 :         if ( sscanf(addr_text,
     229                 :            :                     "%d.%d.%d.%d", addr+0, addr+1, addr+2, addr+3) != 4 )
     230                 :            :                 {
     231                 :          0 :                 error("bad dotted address:", addr_text );
     232                 :          0 :                 return 0;
     233                 :            :                 }
     234                 :            : 
     235 [ +  - ][ +  - ]:         43 :         if ( addr[0] < 0 || addr[1] < 0 || addr[2] < 0 || addr[3] < 0 ||
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
     236                 :            :              addr[0] > 255 || addr[1] > 255 || addr[2] > 255 || addr[3] > 255 )
     237                 :            :                 {
     238                 :          0 :                 error("bad dotted address:", addr_text);
     239                 :          0 :                 return 0;
     240                 :            :                 }
     241                 :            : 
     242                 :         43 :         uint32 a = (addr[0] << 24) | (addr[1] << 16) | (addr[2] << 8) | addr[3];
     243                 :            : 
     244                 :            :         // ### perhaps do gethostbyaddr here?
     245                 :            : 
     246                 :         43 :         return uint32(htonl(a));
     247                 :            :         }
     248                 :            : 
     249                 :            : #ifdef BROv6
     250                 :            : uint32* dotted_to_addr6(const char* addr_text)
     251                 :            :         {
     252                 :            :         uint32* addr = new uint32[4];
     253                 :            :         if ( inet_pton(AF_INET6, addr_text, addr) <= 0 )
     254                 :            :                 {
     255                 :            :                 error("bad IPv6 address:", addr_text );
     256                 :            :                 addr[0] = addr[1] = addr[2] = addr[3] = 0;
     257                 :            :                 }
     258                 :            : 
     259                 :            :         return addr;
     260                 :            :         }
     261                 :            : 
     262                 :            : #endif
     263                 :            : 
     264                 :            : #ifdef BROv6
     265                 :            : int is_v4_addr(const uint32 addr[4])
     266                 :            :         {
     267                 :            :         return addr[0] == 0 && addr[1] == 0 && addr[2] == 0;
     268                 :            :         }
     269                 :            : #endif
     270                 :            : 
     271                 :      46240 : uint32 to_v4_addr(const uint32* addr)
     272                 :            :         {
     273                 :            : #ifdef BROv6
     274                 :            :         if ( ! is_v4_addr(addr) )
     275                 :            :                 internal_error("conversion of non-IPv4 address to IPv4 address");
     276                 :            :         return addr[3];
     277                 :            : #else
     278                 :      46240 :         return addr[0];
     279                 :            : #endif
     280                 :            :         }
     281                 :            : 
     282                 :         14 : uint32 mask_addr(uint32 a, uint32 top_bits_to_keep)
     283                 :            :         {
     284         [ -  + ]:         14 :         if ( top_bits_to_keep > 32 )
     285                 :            :                 {
     286                 :          0 :                 error("bad address mask value", top_bits_to_keep);
     287                 :          0 :                 return a;
     288                 :            :                 }
     289                 :            : 
     290         [ +  + ]:         14 :         if ( top_bits_to_keep == 0 )
     291                 :            :                 // The shifts below don't have any effect with 0, i.e.,
     292                 :            :                 // 1 << 32 does not yield 0; either due to compiler
     293                 :            :                 // misoptimization or language semantics.
     294                 :          1 :                 return 0;
     295                 :            : 
     296                 :         13 :         uint32 addr = ntohl(a);
     297                 :            : 
     298                 :         13 :         int shift = 32 - top_bits_to_keep;
     299                 :         13 :         addr >>= shift;
     300                 :         13 :         addr <<= shift;
     301                 :            : 
     302                 :         14 :         return htonl(addr);
     303                 :            :         }
     304                 :            : 
     305                 :          0 : const uint32* mask_addr(const uint32* a, uint32 top_bits_to_keep)
     306                 :            :         {
     307                 :            : #ifdef BROv6
     308                 :            :         static uint32 addr[4];
     309                 :            : 
     310                 :            :         addr[0] = a[0];
     311                 :            :         addr[1] = a[1];
     312                 :            :         addr[2] = a[2];
     313                 :            :         addr[3] = a[3];
     314                 :            : 
     315                 :            :         // This is a bit dicey: if it's a v4 address, then we interpret
     316                 :            :         // the mask as being with respect to 32 bits total, even though
     317                 :            :         // strictly speaking, the v4 address comprises the least-significant
     318                 :            :         // bits out of 128, rather than the most significant.  However,
     319                 :            :         // we only do this if the mask itself is consistent for a 32-bit
     320                 :            :         // address.
     321                 :            :         uint32 max_bits = (is_v4_addr(a) && top_bits_to_keep <= 32) ? 32 : 128;
     322                 :            : 
     323                 :            :         if ( top_bits_to_keep == 0 || top_bits_to_keep > max_bits )
     324                 :            :                 {
     325                 :            :                 error("bad address mask value", top_bits_to_keep);
     326                 :            :                 return addr;
     327                 :            :                 }
     328                 :            : 
     329                 :            :         int word = 3;   // start zeroing out with word #3
     330                 :            :         int bits_to_chop = max_bits - top_bits_to_keep; // bits to discard
     331                 :            :         while ( bits_to_chop >= 32 )
     332                 :            :                 { // there's an entire word to discard
     333                 :            :                 addr[word] = 0;
     334                 :            :                 --word; // move on to next, more significant word
     335                 :            :                 bits_to_chop -= 32;     // we just go rid of 32 bits
     336                 :            :                 }
     337                 :            : 
     338                 :            :         // All that's left to work with now is the word pointed to by "word".
     339                 :            :         uint32 addr32 = ntohl(addr[word]);
     340                 :            :         addr32 >>= bits_to_chop;
     341                 :            :         addr32 <<= bits_to_chop;
     342                 :            :         addr[word] = htonl(addr32);
     343                 :            : 
     344                 :            :         return addr;
     345                 :            : #else
     346                 :          0 :         return a;
     347                 :            : #endif
     348                 :            :         }
     349                 :            : 
     350                 :            : const char* fmt_conn_id(const uint32* src_addr, uint32 src_port,
     351                 :      22596 :                         const uint32* dst_addr, uint32 dst_port)
     352                 :            :         {
     353                 :            :         char addr1[128], addr2[128];
     354                 :            :         static char buffer[512];
     355                 :            : 
     356                 :      22596 :         strcpy(addr1, dotted_addr(src_addr));
     357                 :      22596 :         strcpy(addr2, dotted_addr(dst_addr));
     358                 :            : 
     359                 :            :         safe_snprintf(buffer, sizeof(buffer), "%s:%d > %s:%d",
     360                 :      22596 :                         addr1, src_port, addr2, dst_port);
     361                 :            : 
     362                 :      22596 :         return buffer;
     363                 :            :         }
     364                 :            : 
     365                 :          0 : uint32 extract_uint32(const u_char* data)
     366                 :            :         {
     367                 :            :         uint32 val;
     368                 :            : 
     369                 :          0 :         val = data[0] << 24;
     370                 :          0 :         val |= data[1] << 16;
     371                 :          0 :         val |= data[2] << 8;
     372                 :          0 :         val |= data[3];
     373                 :            : 
     374                 :          0 :         return val;
     375                 :            :         }

Generated by: LCOV version 1.8