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