1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26#ifndef _CHECKSUM_H
27#define _CHECKSUM_H
28
29#include <asm/types.h>
30#include <asm/byteorder.h>
31#include <net/ip.h>
32#include <linux/in6.h>
33#include <asm/uaccess.h>
34#include <asm/checksum.h>
35
36#ifndef _HAVE_ARCH_IPV6_CSUM
37
38static __inline__ unsigned short int csum_ipv6_magic(struct in6_addr *saddr,
39 struct in6_addr *daddr,
40 __u16 len,
41 unsigned short proto,
42 unsigned int csum)
43{
44
45 int carry;
46 __u32 ulen;
47 __u32 uproto;
48
49 csum += saddr->s6_addr32[0];
50 carry = (csum < saddr->s6_addr32[0]);
51 csum += carry;
52
53 csum += saddr->s6_addr32[1];
54 carry = (csum < saddr->s6_addr32[1]);
55 csum += carry;
56
57 csum += saddr->s6_addr32[2];
58 carry = (csum < saddr->s6_addr32[2]);
59 csum += carry;
60
61 csum += saddr->s6_addr32[3];
62 carry = (csum < saddr->s6_addr32[3]);
63 csum += carry;
64
65 csum += daddr->s6_addr32[0];
66 carry = (csum < daddr->s6_addr32[0]);
67 csum += carry;
68
69 csum += daddr->s6_addr32[1];
70 carry = (csum < daddr->s6_addr32[1]);
71 csum += carry;
72
73 csum += daddr->s6_addr32[2];
74 carry = (csum < daddr->s6_addr32[2]);
75 csum += carry;
76
77 csum += daddr->s6_addr32[3];
78 carry = (csum < daddr->s6_addr32[3]);
79 csum += carry;
80
81 ulen = htonl((__u32) len);
82 csum += ulen;
83 carry = (csum < ulen);
84 csum += carry;
85
86 uproto = htonl(proto);
87 csum += uproto;
88 carry = (csum < uproto);
89 csum += carry;
90
91 return csum_fold(csum);
92}
93
94#endif
95
96#ifndef _HAVE_ARCH_COPY_AND_CSUM_FROM_USER
97static inline
98unsigned int csum_and_copy_from_user (const char *src, char *dst,
99 int len, int sum, int *err_ptr)
100{
101 if (verify_area(VERIFY_READ, src, len) == 0)
102 return csum_partial_copy_from_user(src, dst, len, sum, err_ptr);
103
104 if (len)
105 *err_ptr = -EFAULT;
106
107 return sum;
108}
109#endif
110
111#ifndef HAVE_CSUM_COPY_USER
112static __inline__ unsigned int csum_and_copy_to_user
113(const char *src, char *dst, int len, unsigned int sum, int *err_ptr)
114{
115 sum = csum_partial(src, len, sum);
116
117 if (access_ok(VERIFY_WRITE, dst, len)) {
118 if (copy_to_user(dst, src, len) == 0)
119 return sum;
120 }
121 if (len)
122 *err_ptr = -EFAULT;
123
124 return -1;
125}
126#endif
127
128static inline unsigned int csum_add(unsigned int csum, unsigned int addend)
129{
130 csum += addend;
131 return csum + (csum < addend);
132}
133
134static inline unsigned int csum_sub(unsigned int csum, unsigned int addend)
135{
136 return csum_add(csum, ~addend);
137}
138
139static inline unsigned int
140csum_block_add(unsigned int csum, unsigned int csum2, int offset)
141{
142 if (offset&1)
143 csum2 = ((csum2&0xFF00FF)<<8)+((csum2>>8)&0xFF00FF);
144 return csum_add(csum, csum2);
145}
146
147static inline unsigned int
148csum_block_sub(unsigned int csum, unsigned int csum2, int offset)
149{
150 if (offset&1)
151 csum2 = ((csum2&0xFF00FF)<<8)+((csum2>>8)&0xFF00FF);
152 return csum_sub(csum, csum2);
153}
154
155#endif
156