xref: /plan9/sys/src/cmd/ip/ppp/ipaux.c (revision 312a1df17540496aeba83681557b1b7912ac0023)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <ip.h>
49a747e4fSDavid du Colombier #include <auth.h>
57dd7cddfSDavid du Colombier #include "ppp.h"
67dd7cddfSDavid du Colombier 
77dd7cddfSDavid du Colombier static	ushort	endian	= 1;
87dd7cddfSDavid du Colombier static	uchar*	aendian	= (uchar*)&endian;
97dd7cddfSDavid du Colombier #define	LITTLE	*aendian
107dd7cddfSDavid du Colombier 
117dd7cddfSDavid du Colombier ushort
ptclbsum(uchar * addr,int len)127dd7cddfSDavid du Colombier ptclbsum(uchar *addr, int len)
137dd7cddfSDavid du Colombier {
147dd7cddfSDavid du Colombier 	ulong losum, hisum, mdsum, x;
157dd7cddfSDavid du Colombier 	ulong t1, t2;
167dd7cddfSDavid du Colombier 
177dd7cddfSDavid du Colombier 	losum = 0;
187dd7cddfSDavid du Colombier 	hisum = 0;
197dd7cddfSDavid du Colombier 	mdsum = 0;
207dd7cddfSDavid du Colombier 
217dd7cddfSDavid du Colombier 	x = 0;
22*312a1df1SDavid du Colombier 	if((uintptr)addr & 1) {
237dd7cddfSDavid du Colombier 		if(len) {
247dd7cddfSDavid du Colombier 			hisum += addr[0];
257dd7cddfSDavid du Colombier 			len--;
267dd7cddfSDavid du Colombier 			addr++;
277dd7cddfSDavid du Colombier 		}
287dd7cddfSDavid du Colombier 		x = 1;
297dd7cddfSDavid du Colombier 	}
307dd7cddfSDavid du Colombier 	while(len >= 16) {
317dd7cddfSDavid du Colombier 		t1 = *(ushort*)(addr+0);
327dd7cddfSDavid du Colombier 		t2 = *(ushort*)(addr+2);	mdsum += t1;
337dd7cddfSDavid du Colombier 		t1 = *(ushort*)(addr+4);	mdsum += t2;
347dd7cddfSDavid du Colombier 		t2 = *(ushort*)(addr+6);	mdsum += t1;
357dd7cddfSDavid du Colombier 		t1 = *(ushort*)(addr+8);	mdsum += t2;
367dd7cddfSDavid du Colombier 		t2 = *(ushort*)(addr+10);	mdsum += t1;
377dd7cddfSDavid du Colombier 		t1 = *(ushort*)(addr+12);	mdsum += t2;
387dd7cddfSDavid du Colombier 		t2 = *(ushort*)(addr+14);	mdsum += t1;
397dd7cddfSDavid du Colombier 		mdsum += t2;
407dd7cddfSDavid du Colombier 		len -= 16;
417dd7cddfSDavid du Colombier 		addr += 16;
427dd7cddfSDavid du Colombier 	}
437dd7cddfSDavid du Colombier 	while(len >= 2) {
447dd7cddfSDavid du Colombier 		mdsum += *(ushort*)addr;
457dd7cddfSDavid du Colombier 		len -= 2;
467dd7cddfSDavid du Colombier 		addr += 2;
477dd7cddfSDavid du Colombier 	}
487dd7cddfSDavid du Colombier 	if(x) {
497dd7cddfSDavid du Colombier 		if(len)
507dd7cddfSDavid du Colombier 			losum += addr[0];
517dd7cddfSDavid du Colombier 		if(LITTLE)
527dd7cddfSDavid du Colombier 			losum += mdsum;
537dd7cddfSDavid du Colombier 		else
547dd7cddfSDavid du Colombier 			hisum += mdsum;
557dd7cddfSDavid du Colombier 	} else {
567dd7cddfSDavid du Colombier 		if(len)
577dd7cddfSDavid du Colombier 			hisum += addr[0];
587dd7cddfSDavid du Colombier 		if(LITTLE)
597dd7cddfSDavid du Colombier 			hisum += mdsum;
607dd7cddfSDavid du Colombier 		else
617dd7cddfSDavid du Colombier 			losum += mdsum;
627dd7cddfSDavid du Colombier 	}
637dd7cddfSDavid du Colombier 
647dd7cddfSDavid du Colombier 	losum += hisum >> 8;
657dd7cddfSDavid du Colombier 	losum += (hisum & 0xff) << 8;
667dd7cddfSDavid du Colombier 	while(hisum = losum>>16)
677dd7cddfSDavid du Colombier 		losum = hisum + (losum & 0xffff);
687dd7cddfSDavid du Colombier 
697dd7cddfSDavid du Colombier 	return losum & 0xffff;
707dd7cddfSDavid du Colombier }
717dd7cddfSDavid du Colombier 
727dd7cddfSDavid du Colombier ushort
ptclcsum(Block * bp,int offset,int len)737dd7cddfSDavid du Colombier ptclcsum(Block *bp, int offset, int len)
747dd7cddfSDavid du Colombier {
757dd7cddfSDavid du Colombier 	uchar *addr;
767dd7cddfSDavid du Colombier 	ulong losum, hisum;
777dd7cddfSDavid du Colombier 	ushort csum;
787dd7cddfSDavid du Colombier 	int odd, blen, x;
797dd7cddfSDavid du Colombier 
807dd7cddfSDavid du Colombier 	/* Correct to front of data area */
817dd7cddfSDavid du Colombier 	while(bp != nil && offset && offset >= BLEN(bp)) {
827dd7cddfSDavid du Colombier 		offset -= BLEN(bp);
837dd7cddfSDavid du Colombier 		bp = bp->next;
847dd7cddfSDavid du Colombier 	}
857dd7cddfSDavid du Colombier 	if(bp == nil)
867dd7cddfSDavid du Colombier 		return 0;
877dd7cddfSDavid du Colombier 
887dd7cddfSDavid du Colombier 	addr = bp->rptr + offset;
897dd7cddfSDavid du Colombier 	blen = BLEN(bp) - offset;
907dd7cddfSDavid du Colombier 
917dd7cddfSDavid du Colombier 	if(bp->next == nil) {
927dd7cddfSDavid du Colombier 		if(blen < len)
937dd7cddfSDavid du Colombier 			len = blen;
947dd7cddfSDavid du Colombier 		return ~ptclbsum(addr, len) & 0xffff;
957dd7cddfSDavid du Colombier 	}
967dd7cddfSDavid du Colombier 
977dd7cddfSDavid du Colombier 	losum = 0;
987dd7cddfSDavid du Colombier 	hisum = 0;
997dd7cddfSDavid du Colombier 
1007dd7cddfSDavid du Colombier 	odd = 0;
1017dd7cddfSDavid du Colombier 	while(len) {
1027dd7cddfSDavid du Colombier 		x = blen;
1037dd7cddfSDavid du Colombier 		if(len < x)
1047dd7cddfSDavid du Colombier 			x = len;
1057dd7cddfSDavid du Colombier 
1067dd7cddfSDavid du Colombier 		csum = ptclbsum(addr, x);
1077dd7cddfSDavid du Colombier 		if(odd)
1087dd7cddfSDavid du Colombier 			hisum += csum;
1097dd7cddfSDavid du Colombier 		else
1107dd7cddfSDavid du Colombier 			losum += csum;
1117dd7cddfSDavid du Colombier 		odd = (odd+x) & 1;
1127dd7cddfSDavid du Colombier 		len -= x;
1137dd7cddfSDavid du Colombier 
1147dd7cddfSDavid du Colombier 		bp = bp->next;
1157dd7cddfSDavid du Colombier 		if(bp == nil)
1167dd7cddfSDavid du Colombier 			break;
1177dd7cddfSDavid du Colombier 		blen = BLEN(bp);
1187dd7cddfSDavid du Colombier 		addr = bp->rptr;
1197dd7cddfSDavid du Colombier 	}
1207dd7cddfSDavid du Colombier 
1217dd7cddfSDavid du Colombier 	losum += hisum>>8;
1227dd7cddfSDavid du Colombier 	losum += (hisum&0xff)<<8;
1237dd7cddfSDavid du Colombier 	while((csum = losum>>16) != 0)
1247dd7cddfSDavid du Colombier 		losum = csum + (losum & 0xffff);
1257dd7cddfSDavid du Colombier 
1267dd7cddfSDavid du Colombier 	return ~losum & 0xffff;
1277dd7cddfSDavid du Colombier }
1287dd7cddfSDavid du Colombier 
1297dd7cddfSDavid du Colombier ushort
ipcsum(uchar * addr)1307dd7cddfSDavid du Colombier ipcsum(uchar *addr)
1317dd7cddfSDavid du Colombier {
1327dd7cddfSDavid du Colombier 	int len;
1337dd7cddfSDavid du Colombier 	ulong sum;
1347dd7cddfSDavid du Colombier 
1357dd7cddfSDavid du Colombier 	sum = 0;
1367dd7cddfSDavid du Colombier 	len = (addr[0]&0xf)<<2;
1377dd7cddfSDavid du Colombier 
1387dd7cddfSDavid du Colombier 	while(len > 0) {
1397dd7cddfSDavid du Colombier 		sum += (addr[0]<<8) | addr[1] ;
1407dd7cddfSDavid du Colombier 		len -= 2;
1417dd7cddfSDavid du Colombier 		addr += 2;
1427dd7cddfSDavid du Colombier 	}
1437dd7cddfSDavid du Colombier 
1447dd7cddfSDavid du Colombier 	sum = (sum & 0xffff) + (sum >> 16);
1457dd7cddfSDavid du Colombier 	sum = (sum & 0xffff) + (sum >> 16);
1467dd7cddfSDavid du Colombier 
1477dd7cddfSDavid du Colombier 	return (sum^0xffff);
1487dd7cddfSDavid du Colombier }
149