Annotation of embedaddon/quagga/lib/checksum.c, revision 1.1

1.1     ! misho       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: in_cksum(void *parg, int nbytes)
        !            14: {
        !            15:        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:        sum = 0;
        !            27:        while (nbytes > 1)  {
        !            28:                sum += *ptr++;
        !            29:                nbytes -= 2;
        !            30:        }
        !            31: 
        !            32:                                /* mop up an odd byte, if necessary */
        !            33:        if (nbytes == 1) {
        !            34:                oddbyte = 0;            /* make sure top half is zero */
        !            35:                *((u_char *) &oddbyte) = *(u_char *)ptr;   /* one byte only */
        !            36:                sum += oddbyte;
        !            37:        }
        !            38: 
        !            39:        /*
        !            40:         * Add back carry outs from top 16 bits to low 16 bits.
        !            41:         */
        !            42: 
        !            43:        sum  = (sum >> 16) + (sum & 0xffff);    /* add high-16 to low-16 */
        !            44:        sum += (sum >> 16);                     /* add carry */
        !            45:        answer = ~sum;          /* ones-complement, then truncate to 16 bits */
        !            46:        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: u_int16_t
        !            55: fletcher_checksum(u_char * buffer, const size_t len, const uint16_t offset)
        !            56: {
        !            57:   u_int8_t *p;
        !            58:   int x, y, c0, c1;
        !            59:   u_int16_t checksum;
        !            60:   u_int16_t *csum;
        !            61:   size_t partial_len, i, left = len;
        !            62:   
        !            63:   checksum = 0;
        !            64: 
        !            65:   assert (offset < len);
        !            66: 
        !            67:   /*
        !            68:    * Zero the csum in the packet.
        !            69:    */
        !            70:   csum = (u_int16_t *) (buffer + offset);
        !            71:   *(csum) = 0;
        !            72: 
        !            73:   p = buffer;
        !            74:   c0 = 0;
        !            75:   c1 = 0;
        !            76: 
        !            77:   while (left != 0)
        !            78:     {
        !            79:       partial_len = MIN(left, MODX);
        !            80: 
        !            81:       for (i = 0; i < partial_len; i++)
        !            82:        {
        !            83:          c0 = c0 + *(p++);
        !            84:          c1 += c0;
        !            85:        }
        !            86: 
        !            87:       c0 = c0 % 255;
        !            88:       c1 = c1 % 255;
        !            89: 
        !            90:       left -= partial_len;
        !            91:     }
        !            92:   
        !            93:   /* The cast is important, to ensure the mod is taken as a signed value. */
        !            94:   x = (int)((len - offset - 1) * c0 - c1) % 255;
        !            95: 
        !            96:   if (x <= 0)
        !            97:     x += 255;
        !            98:   y = 510 - c0 - x;
        !            99:   if (y > 255)  
        !           100:     y -= 255;
        !           101:   
        !           102:   /*
        !           103:    * Now we write this to the packet.
        !           104:    * We could skip this step too, since the checksum returned would
        !           105:    * be stored into the checksum field by the caller.
        !           106:    */
        !           107:   buffer[offset] = x;
        !           108:   buffer[offset + 1] = y;
        !           109: 
        !           110:   /* Take care of the endian issue */
        !           111:   checksum = htons((x << 8) | (y & 0xFF));
        !           112: 
        !           113:   return checksum;
        !           114: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>