Statistics
| Branch: | Revision:

iof-bird / bird-2.0.1 / lib / checksum.c @ 6b3f1a54

History | View | Annotate | Download (2.39 KB)

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
}