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>