Annotation of embedaddon/bird/lib/checksum.c, revision 1.1.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>