diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Modules | 2 | ||||
-rw-r--r-- | lib/checksum.c | 59 | ||||
-rw-r--r-- | lib/checksum.h | 20 |
3 files changed, 81 insertions, 0 deletions
diff --git a/lib/Modules b/lib/Modules index 19a79000..1597b9af 100644 --- a/lib/Modules +++ b/lib/Modules @@ -27,3 +27,5 @@ slists.c slists.h event.c event.h +checksum.c +checksum.h diff --git a/lib/checksum.c b/lib/checksum.c new file mode 100644 index 00000000..4dfa2520 --- /dev/null +++ b/lib/checksum.c @@ -0,0 +1,59 @@ +/* + * BIRD Library -- IP One-Complement Checksum + * + * (c) 1999 Martin Mares <mj@ucw.cz> + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +#include <stdarg.h> + +#include "nest/bird.h" +#include "checksum.h" + +static u16 +ipsum_calc(void *frag, unsigned len, va_list args) +{ + u16 sum = 0; + + for(;;) + { + u16 *x = frag; + ASSERT(!(len % 2)); + while (len) + { + u16 z = sum + *x++; + sum = z + (z < sum); + len -= 2; + } + frag = va_arg(args, void *); + if (!frag) + break; + len = va_arg(args, unsigned); + } + return sum; +} + +int +ipsum_verify(void *frag, unsigned len, ...) +{ + va_list args; + u16 sum; + + va_start(args, len); + sum = ipsum_calc(frag, len, args); + va_end(args); + return sum == 0xffff; +} + +u16 +ipsum_calculate(void *frag, unsigned len, ...) +{ + va_list args; + u16 sum; + + va_start(args, len); + sum = ipsum_calc(frag, len, args); + va_end(args); + return 0xffff - sum; +} diff --git a/lib/checksum.h b/lib/checksum.h new file mode 100644 index 00000000..81515543 --- /dev/null +++ b/lib/checksum.h @@ -0,0 +1,20 @@ +/* + * BIRD Library -- IP One-Complement Checksum + * + * (c) 1999 Martin Mares <mj@ucw.cz> + * + * Can be freely distributed and used under the terms of the GNU GPL. + */ + +#ifndef _BIRD_CHECKSUM_H_ +#define _BIRD_CHECKSUM_H_ + +/* + * Both checksumming functions accept a vararg list of packet + * fragments finished by NULL pointer. + */ + +int ipsum_verify(void *frag, unsigned len, ...); +u16 ipsum_calculate(void *frag, unsigned len, ...); + +#endif |