File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / bird / lib / checksum.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Aug 22 12:33:54 2017 UTC (6 years, 10 months ago) by misho
Branches: bird, MAIN
CVS tags: v1_6_8p3, v1_6_3p0, v1_6_3, HEAD
bird 1.6.3

    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>