Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

#include <u.h>
#include <libc.h>
#include <ip.h>
#include <auth.h>
#include "ppp.h"

static  ushort  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((uintptr)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;
}

ushort
ptclcsum(Block *bp, int offset, int len)
{
        uchar *addr;
        ulong losum, hisum;
        ushort csum;
        int odd, blen, x;

        /* Correct to front of data area */
        while(bp != nil && offset && offset >= BLEN(bp)) {
                offset -= BLEN(bp);
                bp = bp->next;
        }
        if(bp == nil)
                return 0;

        addr = bp->rptr + offset;
        blen = BLEN(bp) - offset;

        if(bp->next == nil) {
                if(blen < len)
                        len = blen;
                return ~ptclbsum(addr, len) & 0xffff;
        }

        losum = 0;
        hisum = 0;

        odd = 0;
        while(len) {
                x = blen;
                if(len < x)
                        x = len;

                csum = ptclbsum(addr, x);
                if(odd)
                        hisum += csum;
                else
                        losum += csum;
                odd = (odd+x) & 1;
                len -= x;

                bp = bp->next;
                if(bp == nil)
                        break;
                blen = BLEN(bp);
                addr = bp->rptr;
        }

        losum += hisum>>8;
        losum += (hisum&0xff)<<8;
        while((csum = losum>>16) != 0)
                losum = csum + (losum & 0xffff);

        return ~losum & 0xffff;
}

ushort
ipcsum(uchar *addr)
{
        int len;
        ulong sum;

        sum = 0;
        len = (addr[0]&0xf)<<2;

        while(len > 0) {
                sum += (addr[0]<<8) | addr[1] ;
                len -= 2;
                addr += 2;
        }

        sum = (sum & 0xffff) + (sum >> 16);
        sum = (sum & 0xffff) + (sum >> 16);

        return (sum^0xffff);
}