LCOV - code coverage report
Current view: top level - lib - checksum.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 44 0.0 %
Date: 2015-11-19 Functions: 0 2 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Checksum routine for Internet Protocol family headers (C Version).
       3             :  *
       4             :  * Refer to "Computing the Internet Checksum" by R. Braden, D. Borman and
       5             :  * C. Partridge, Computer Communication Review, Vol. 19, No. 2, April 1989,
       6             :  * pp. 86-101, for additional details on computing this checksum.
       7             :  */
       8             : 
       9             : #include <zebra.h>
      10             : #include "checksum.h"
      11             : 
      12             : int                     /* return checksum in low-order 16 bits */
      13           0 : in_cksum(void *parg, int nbytes)
      14             : {
      15           0 :         u_short *ptr = parg;
      16             :         register long           sum;            /* assumes long == 32 bits */
      17             :         u_short                 oddbyte;
      18             :         register u_short        answer;         /* assumes u_short == 16 bits */
      19             : 
      20             :         /*
      21             :          * Our algorithm is simple, using a 32-bit accumulator (sum),
      22             :          * we add sequential 16-bit words to it, and at the end, fold back
      23             :          * all the carry bits from the top 16 bits into the lower 16 bits.
      24             :          */
      25             : 
      26           0 :         sum = 0;
      27           0 :         while (nbytes > 1)  {
      28           0 :                 sum += *ptr++;
      29           0 :                 nbytes -= 2;
      30             :         }
      31             : 
      32             :                                 /* mop up an odd byte, if necessary */
      33           0 :         if (nbytes == 1) {
      34           0 :                 oddbyte = 0;            /* make sure top half is zero */
      35           0 :                 *((u_char *) &oddbyte) = *(u_char *)ptr;   /* one byte only */
      36           0 :                 sum += oddbyte;
      37             :         }
      38             : 
      39             :         /*
      40             :          * Add back carry outs from top 16 bits to low 16 bits.
      41             :          */
      42             : 
      43           0 :         sum  = (sum >> 16) + (sum & 0xffff);  /* add high-16 to low-16 */
      44           0 :         sum += (sum >> 16);                       /* add carry */
      45           0 :         answer = ~sum;          /* ones-complement, then truncate to 16 bits */
      46           0 :         return(answer);
      47             : }
      48             : 
      49             : /* Fletcher Checksum -- Refer to RFC1008. */
      50             : #define MODX                 4102   /* 5802 should be fine */
      51             : 
      52             : /* To be consistent, offset is 0-based index, rather than the 1-based 
      53             :    index required in the specification ISO 8473, Annex C.1 */
      54             : /* calling with offset == FLETCHER_CHECKSUM_VALIDATE will validate the checksum
      55             :    without modifying the buffer; a valid checksum returns 0 */
      56             : u_int16_t
      57           0 : fletcher_checksum(u_char * buffer, const size_t len, const uint16_t offset)
      58             : {
      59             :   u_int8_t *p;
      60             :   int x, y, c0, c1;
      61             :   u_int16_t checksum;
      62             :   u_int16_t *csum;
      63           0 :   size_t partial_len, i, left = len;
      64             :   
      65           0 :   checksum = 0;
      66             : 
      67             : 
      68           0 :   if (offset != FLETCHER_CHECKSUM_VALIDATE)
      69             :     /* Zero the csum in the packet. */
      70             :     {
      71           0 :       assert (offset < (len - 1)); /* account for two bytes of checksum */
      72           0 :       csum = (u_int16_t *) (buffer + offset);
      73           0 :       *(csum) = 0;
      74             :     }
      75             : 
      76           0 :   p = buffer;
      77           0 :   c0 = 0;
      78           0 :   c1 = 0;
      79             : 
      80           0 :   while (left != 0)
      81             :     {
      82           0 :       partial_len = MIN(left, MODX);
      83             : 
      84           0 :       for (i = 0; i < partial_len; i++)
      85             :         {
      86           0 :           c0 = c0 + *(p++);
      87           0 :           c1 += c0;
      88             :         }
      89             : 
      90           0 :       c0 = c0 % 255;
      91           0 :       c1 = c1 % 255;
      92             : 
      93           0 :       left -= partial_len;
      94             :     }
      95             : 
      96             :   /* The cast is important, to ensure the mod is taken as a signed value. */
      97           0 :   x = (int)((len - offset - 1) * c0 - c1) % 255;
      98             : 
      99           0 :   if (x <= 0)
     100           0 :     x += 255;
     101           0 :   y = 510 - c0 - x;
     102           0 :   if (y > 255)  
     103           0 :     y -= 255;
     104             : 
     105           0 :   if (offset == FLETCHER_CHECKSUM_VALIDATE)
     106             :     {
     107           0 :       checksum = (c1 << 8) + c0;
     108             :     }
     109             :   else
     110             :     {
     111             :       /*
     112             :        * Now we write this to the packet.
     113             :        * We could skip this step too, since the checksum returned would
     114             :        * be stored into the checksum field by the caller.
     115             :        */
     116           0 :       buffer[offset] = x;
     117           0 :       buffer[offset + 1] = y;
     118             : 
     119             :       /* Take care of the endian issue */
     120           0 :       checksum = htons((x << 8) | (y & 0xFF));
     121             :     }
     122             : 
     123           0 :   return checksum;
     124             : }

Generated by: LCOV version 1.10