xref: /plan9/sys/src/cmd/ip/ppp/ipaux.c (revision 312a1df17540496aeba83681557b1b7912ac0023)
1 #include <u.h>
2 #include <libc.h>
3 #include <ip.h>
4 #include <auth.h>
5 #include "ppp.h"
6 
7 static	ushort	endian	= 1;
8 static	uchar*	aendian	= (uchar*)&endian;
9 #define	LITTLE	*aendian
10 
11 ushort
ptclbsum(uchar * addr,int len)12 ptclbsum(uchar *addr, int len)
13 {
14 	ulong losum, hisum, mdsum, x;
15 	ulong t1, t2;
16 
17 	losum = 0;
18 	hisum = 0;
19 	mdsum = 0;
20 
21 	x = 0;
22 	if((uintptr)addr & 1) {
23 		if(len) {
24 			hisum += addr[0];
25 			len--;
26 			addr++;
27 		}
28 		x = 1;
29 	}
30 	while(len >= 16) {
31 		t1 = *(ushort*)(addr+0);
32 		t2 = *(ushort*)(addr+2);	mdsum += t1;
33 		t1 = *(ushort*)(addr+4);	mdsum += t2;
34 		t2 = *(ushort*)(addr+6);	mdsum += t1;
35 		t1 = *(ushort*)(addr+8);	mdsum += t2;
36 		t2 = *(ushort*)(addr+10);	mdsum += t1;
37 		t1 = *(ushort*)(addr+12);	mdsum += t2;
38 		t2 = *(ushort*)(addr+14);	mdsum += t1;
39 		mdsum += t2;
40 		len -= 16;
41 		addr += 16;
42 	}
43 	while(len >= 2) {
44 		mdsum += *(ushort*)addr;
45 		len -= 2;
46 		addr += 2;
47 	}
48 	if(x) {
49 		if(len)
50 			losum += addr[0];
51 		if(LITTLE)
52 			losum += mdsum;
53 		else
54 			hisum += mdsum;
55 	} else {
56 		if(len)
57 			hisum += addr[0];
58 		if(LITTLE)
59 			hisum += mdsum;
60 		else
61 			losum += mdsum;
62 	}
63 
64 	losum += hisum >> 8;
65 	losum += (hisum & 0xff) << 8;
66 	while(hisum = losum>>16)
67 		losum = hisum + (losum & 0xffff);
68 
69 	return losum & 0xffff;
70 }
71 
72 ushort
ptclcsum(Block * bp,int offset,int len)73 ptclcsum(Block *bp, int offset, int len)
74 {
75 	uchar *addr;
76 	ulong losum, hisum;
77 	ushort csum;
78 	int odd, blen, x;
79 
80 	/* Correct to front of data area */
81 	while(bp != nil && offset && offset >= BLEN(bp)) {
82 		offset -= BLEN(bp);
83 		bp = bp->next;
84 	}
85 	if(bp == nil)
86 		return 0;
87 
88 	addr = bp->rptr + offset;
89 	blen = BLEN(bp) - offset;
90 
91 	if(bp->next == nil) {
92 		if(blen < len)
93 			len = blen;
94 		return ~ptclbsum(addr, len) & 0xffff;
95 	}
96 
97 	losum = 0;
98 	hisum = 0;
99 
100 	odd = 0;
101 	while(len) {
102 		x = blen;
103 		if(len < x)
104 			x = len;
105 
106 		csum = ptclbsum(addr, x);
107 		if(odd)
108 			hisum += csum;
109 		else
110 			losum += csum;
111 		odd = (odd+x) & 1;
112 		len -= x;
113 
114 		bp = bp->next;
115 		if(bp == nil)
116 			break;
117 		blen = BLEN(bp);
118 		addr = bp->rptr;
119 	}
120 
121 	losum += hisum>>8;
122 	losum += (hisum&0xff)<<8;
123 	while((csum = losum>>16) != 0)
124 		losum = csum + (losum & 0xffff);
125 
126 	return ~losum & 0xffff;
127 }
128 
129 ushort
ipcsum(uchar * addr)130 ipcsum(uchar *addr)
131 {
132 	int len;
133 	ulong sum;
134 
135 	sum = 0;
136 	len = (addr[0]&0xf)<<2;
137 
138 	while(len > 0) {
139 		sum += (addr[0]<<8) | addr[1] ;
140 		len -= 2;
141 		addr += 2;
142 	}
143 
144 	sum = (sum & 0xffff) + (sum >> 16);
145 	sum = (sum & 0xffff) + (sum >> 16);
146 
147 	return (sum^0xffff);
148 }
149