]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * INET An implementation of the TCP/IP protocol suite for the LINUX | |
3 | * operating system. INET is implemented using the BSD Socket | |
4 | * interface as the means of communication with the user level. | |
5 | * | |
6 | * Checksumming functions for IP, TCP, UDP and so on | |
7 | * | |
8 | * Authors: Jorge Cwik, <jorge@laser.satlink.net> | |
9 | * Arnt Gulbrandsen, <agulbra@nvg.unit.no> | |
10 | * Borrows very liberally from tcp.c and ip.c, see those | |
11 | * files for more names. | |
12 | * | |
13 | * This program is free software; you can redistribute it and/or | |
14 | * modify it under the terms of the GNU General Public License | |
15 | * as published by the Free Software Foundation; either version | |
16 | * 2 of the License, or (at your option) any later version. | |
17 | */ | |
18 | ||
19 | #ifndef _CHECKSUM_H | |
20 | #define _CHECKSUM_H | |
21 | ||
22 | #include <linux/errno.h> | |
23 | #include <asm/types.h> | |
24 | #include <asm/byteorder.h> | |
25 | #include <asm/uaccess.h> | |
26 | #include <asm/checksum.h> | |
27 | ||
28 | #ifndef _HAVE_ARCH_COPY_AND_CSUM_FROM_USER | |
29 | static inline | |
30 | unsigned int csum_and_copy_from_user (const unsigned char __user *src, unsigned char *dst, | |
31 | int len, int sum, int *err_ptr) | |
32 | { | |
33 | if (access_ok(VERIFY_READ, src, len)) | |
34 | return csum_partial_copy_from_user(src, dst, len, sum, err_ptr); | |
35 | ||
36 | if (len) | |
37 | *err_ptr = -EFAULT; | |
38 | ||
39 | return sum; | |
40 | } | |
41 | #endif | |
42 | ||
43 | #ifndef HAVE_CSUM_COPY_USER | |
44 | static __inline__ unsigned int csum_and_copy_to_user | |
45 | (const unsigned char *src, unsigned char __user *dst, int len, unsigned int sum, int *err_ptr) | |
46 | { | |
47 | sum = csum_partial(src, len, sum); | |
48 | ||
49 | if (access_ok(VERIFY_WRITE, dst, len)) { | |
50 | if (copy_to_user(dst, src, len) == 0) | |
51 | return sum; | |
52 | } | |
53 | if (len) | |
54 | *err_ptr = -EFAULT; | |
55 | ||
56 | return -1; /* invalid checksum */ | |
57 | } | |
58 | #endif | |
59 | ||
60 | static inline unsigned int csum_add(unsigned int csum, unsigned int addend) | |
61 | { | |
62 | csum += addend; | |
63 | return csum + (csum < addend); | |
64 | } | |
65 | ||
66 | static inline unsigned int csum_sub(unsigned int csum, unsigned int addend) | |
67 | { | |
68 | return csum_add(csum, ~addend); | |
69 | } | |
70 | ||
71 | static inline unsigned int | |
72 | csum_block_add(unsigned int csum, unsigned int csum2, int offset) | |
73 | { | |
74 | if (offset&1) | |
75 | csum2 = ((csum2&0xFF00FF)<<8)+((csum2>>8)&0xFF00FF); | |
76 | return csum_add(csum, csum2); | |
77 | } | |
78 | ||
79 | static inline unsigned int | |
80 | csum_block_sub(unsigned int csum, unsigned int csum2, int offset) | |
81 | { | |
82 | if (offset&1) | |
83 | csum2 = ((csum2&0xFF00FF)<<8)+((csum2>>8)&0xFF00FF); | |
84 | return csum_sub(csum, csum2); | |
85 | } | |
86 | ||
87 | #endif |