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

1.1     ! misho       1: /*
        !             2:  *     BIRD Library -- IP One-Complement Checksum
        !             3:  *
        !             4:  *     (c) 1999--2000 Martin Mares <mj@ucw.cz>
        !             5:  *
        !             6:  *     Can be freely distributed and used under the terms of the GNU GPL.
        !             7:  */
        !             8: 
        !             9: /**
        !            10:  * DOC: Miscellaneous functions.
        !            11:  */
        !            12: 
        !            13: #include <stdarg.h>
        !            14: 
        !            15: #include "nest/bird.h"
        !            16: #include "checksum.h"
        !            17: 
        !            18: static inline u32
        !            19: add32(u32 sum, u32 x)
        !            20: {
        !            21:   u32 z = sum + x;
        !            22: //  return z + (z < sum);
        !            23: 
        !            24:  /* add carry */
        !            25:   if (z < x)
        !            26:     z++;
        !            27:   return z;
        !            28: }
        !            29: 
        !            30: static u16
        !            31: ipsum_calc_block(u32 *buf, uint len, u16 isum)
        !            32: {
        !            33:   /*
        !            34:    *  A few simple facts about the IP checksum (see RFC 1071 for detailed
        !            35:    *  discussion):
        !            36:    *
        !            37:    *   o  It's associative and commutative.
        !            38:    *   o  It's byte order independent.
        !            39:    *   o  It's word size independent.
        !            40:    *
        !            41:    *  This gives us a neat 32-bits-at-a-time algorithm which respects
        !            42:    *  usual alignment requirements and is reasonably fast.
        !            43:    */
        !            44: 
        !            45:   ASSERT(!(len % 4));
        !            46:   if (!len)
        !            47:     return isum;
        !            48: 
        !            49:   u32 *end = buf + (len >> 2);
        !            50:   u32 sum = isum;
        !            51:   while (buf < end)
        !            52:     sum = add32(sum, *buf++);
        !            53: 
        !            54:   sum = (sum >> 16) + (sum & 0xffff);    /* add high-16 to low-16 */
        !            55:   sum += (sum >> 16); /* add carry */
        !            56:   return sum;
        !            57: }
        !            58: 
        !            59: static u16
        !            60: ipsum_calc(void *frag, uint len, va_list args)
        !            61: {
        !            62:   u16 sum = 0;
        !            63: 
        !            64:   for(;;)
        !            65:     {
        !            66:       sum = ipsum_calc_block(frag, len, sum);
        !            67:       frag = va_arg(args, void *);
        !            68:       if (!frag)
        !            69:        break;
        !            70:       len = va_arg(args, uint);
        !            71:     }
        !            72:   return sum;
        !            73: }
        !            74: 
        !            75: /**
        !            76:  * ipsum_verify - verify an IP checksum
        !            77:  * @frag: first packet fragment
        !            78:  * @len: length in bytes
        !            79:  *
        !            80:  * This function verifies whether a given fragmented packet
        !            81:  * has correct one's complement checksum as used by the IP
        !            82:  * protocol.
        !            83:  *
        !            84:  * It uses all the clever tricks described in RFC 1071 to speed
        !            85:  * up checksum calculation as much as possible.
        !            86:  *
        !            87:  * Result: 1 if the checksum is correct, 0 else.
        !            88:  */
        !            89: int
        !            90: ipsum_verify(void *frag, uint len, ...)
        !            91: {
        !            92:   va_list args;
        !            93:   u16 sum;
        !            94: 
        !            95:   va_start(args, len);
        !            96:   sum = ipsum_calc(frag, len, args);
        !            97:   va_end(args);
        !            98:   return sum == 0xffff;
        !            99: }
        !           100: 
        !           101: /**
        !           102:  * ipsum_calculate - compute an IP checksum
        !           103:  * @frag: first packet fragment
        !           104:  * @len: length in bytes
        !           105:  *
        !           106:  * This function calculates a one's complement checksum of a given fragmented
        !           107:  * packet.
        !           108:  *
        !           109:  * It uses all the clever tricks described in RFC 1071 to speed
        !           110:  * up checksum calculation as much as possible.
        !           111:  */
        !           112: u16
        !           113: ipsum_calculate(void *frag, uint len, ...)
        !           114: {
        !           115:   va_list args;
        !           116:   u16 sum;
        !           117: 
        !           118:   va_start(args, len);
        !           119:   sum = ipsum_calc(frag, len, args);
        !           120:   va_end(args);
        !           121:   return 0xffff - sum;
        !           122: }

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