diff options
Diffstat (limited to 'src/libip/ptclbsum.c')
-rw-r--r-- | src/libip/ptclbsum.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/src/libip/ptclbsum.c b/src/libip/ptclbsum.c new file mode 100644 index 00000000..d87815bc --- /dev/null +++ b/src/libip/ptclbsum.c @@ -0,0 +1,68 @@ +#include <u.h> +#include <libc.h> +#include <ip.h> + +static short endian = 1; +static uchar* aendian = (uchar*)&endian; +#define LITTLE *aendian + +ushort +ptclbsum(uchar *addr, int len) +{ + ulong losum, hisum, mdsum, x; + ulong t1, t2; + + losum = 0; + hisum = 0; + mdsum = 0; + + x = 0; + if((ulong)addr & 1) { + if(len) { + hisum += addr[0]; + len--; + addr++; + } + x = 1; + } + while(len >= 16) { + t1 = *(ushort*)(addr+0); + t2 = *(ushort*)(addr+2); mdsum += t1; + t1 = *(ushort*)(addr+4); mdsum += t2; + t2 = *(ushort*)(addr+6); mdsum += t1; + t1 = *(ushort*)(addr+8); mdsum += t2; + t2 = *(ushort*)(addr+10); mdsum += t1; + t1 = *(ushort*)(addr+12); mdsum += t2; + t2 = *(ushort*)(addr+14); mdsum += t1; + mdsum += t2; + len -= 16; + addr += 16; + } + while(len >= 2) { + mdsum += *(ushort*)addr; + len -= 2; + addr += 2; + } + if(x) { + if(len) + losum += addr[0]; + if(LITTLE) + losum += mdsum; + else + hisum += mdsum; + } else { + if(len) + hisum += addr[0]; + if(LITTLE) + hisum += mdsum; + else + losum += mdsum; + } + + losum += hisum >> 8; + losum += (hisum & 0xff) << 8; + while(hisum = losum>>16) + losum = hisum + (losum & 0xffff); + + return losum & 0xffff; +} |