1: /*************************************************************************
2: * (C) 2008 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
3: * by Michael Pounov <misho@openbsd-bg.org>
4: *
5: * $Author: misho $
6: * $Id: aitcrc.c,v 1.2 2010/01/20 00:04:45 misho Exp $
7: *
8: *************************************************************************/
9: #include "global.h"
10:
11:
12: static int crc_Errno;
13: static char crc_Error[MAX_STR + 1];
14:
15: // Adler module
16: const u_long crc_modAdler = 0xFFF1L;
17:
18: // All known library CRC types ...
19: const crcPoly_t crc_Poly[] = {
20: { 1, (u_long) 0x1, "CRC-1-Parity" },
21: { 4, (u_long) 0x3, "CRC-4-ITU" },
22: { 5, (u_long) 0x15, "CRC-5-ITU" },
23: { 6, (u_long) 0x3, "CRC-6-ITU" },
24: { 7, (u_long) 0x9, "CRC-7-MMC" },
25: { 8, (u_long) 0x8D, "CRC-8-CCITT" },
26: { 10, (u_long) 0x233, "CRC-10" },
27: { 11, (u_long) 0x385, "CRC-11-FlexRay" },
28: { 12, (u_long) 0x80F, "CRC-12-Telco" },
29: { 15, (u_long) 0x4599, "CRC-15-CAN" },
30: { 16, (u_long) 0x8005, "CRC-16-IBM" },
31: { 24, (u_long) 0x864CFB, "CRC-24-Radix64" },
32: { 30, (u_long) 0x2030B9C7, "CRC-30-CDMA" },
33: { 32, (u_long) 0x04C11DB7, "CRC-32-802.3" }
34: };
35:
36: // ----------------------------------------------------------
37:
38: //
39: // Error maintenance functions ...
40: //
41:
42: // crc_GetErrno() Get error code of last operation
43: inline int crc_GetErrno()
44: {
45: return crc_Errno;
46: }
47:
48: // crc_GetError() Get error text of last operation
49: inline const char *crc_GetError()
50: {
51: return crc_Error;
52: }
53:
54: // crcSetErr() Set error to variables for internal use!!!
55: inline void crcSetErr(int eno, char *estr, ...)
56: {
57: va_list lst;
58:
59: crc_Errno = eno;
60: memset(crc_Error, 0, MAX_STR + 1);
61: va_start(lst, estr);
62: vsnprintf(crc_Error, MAX_STR + 1, estr, lst);
63: va_end(lst);
64: }
65:
66: // ----------------------------------------------------------
67:
68: /*
69: * crcReflect() Reflect all bits of number
70: * @crcNum = Number for reflection
71: * @crcBits = Number width bits
72: * return: -1 error, !=-1 reflecting number
73: */
74: inline u_long crcReflect(u_long crcNum, u_char crcBits)
75: {
76: register u_long i, j, rev;
77:
78: for (i = (u_long) 1 << (crcBits - 1), j = 1, rev ^= rev; i; i >>= 1, j <<= 1)
79: if (crcNum & i)
80: rev |= j;
81:
82: crc_Errno ^= crc_Errno;
83: return rev;
84: }
85:
86: /*
87: * crcCalc() Generic CRC calculation function for many sub variants of CRC algorithms
88: * @psBuf = Data for calculation
89: * @bufLen = Length of data
90: * @crcBits = CRC algorithm bits (1, 4, 5, 6, 7, 8, 10, 11, 12, 15, 16, 24, 30, 32)
91: * @RevOpts = Options for computation (REVOPTS_REVERTBYTE, REVOPTS_REVERTCRC)
92: * @initCRC = Initial CRC value
93: * @xorCRC = Last xor CRC value
94: * return: -1 error, !=-1 CRC checksum
95: */
96: inline u_long crcCalc(u_char * __restrict psBuf, u_int bufLen, u_char crcBits, u_char RevOpts, u_long initCRC, u_long xorCRC)
97: {
98: const u_long bits = sizeof(long) * 8 - crcBits;
99: u_long poly, crchibit, crc;
100: register u_long i, j, b, ch;
101:
102: if (!psBuf) {
103: crc_Errno = 1;
104: strlcpy(crc_Error, "crcCalc(): Invalid parameters!", MAX_STR + 1);
105: return -1;
106: }
107:
108: switch (crcBits) {
109: case 1:
110: poly = crc_Poly[0].poly_num;
111: break;
112: case 4:
113: poly = crc_Poly[1].poly_num;
114: break;
115: case 5:
116: poly = crc_Poly[2].poly_num;
117: break;
118: case 6:
119: poly = crc_Poly[3].poly_num;
120: break;
121: case 7:
122: poly = crc_Poly[4].poly_num;
123: break;
124: case 8:
125: poly = crc_Poly[5].poly_num;
126: break;
127: case 10:
128: poly = crc_Poly[6].poly_num;
129: break;
130: case 11:
131: poly = crc_Poly[7].poly_num;
132: break;
133: case 12:
134: poly = crc_Poly[8].poly_num;
135: break;
136: case 15:
137: poly = crc_Poly[9].poly_num;
138: break;
139: case 16:
140: poly = crc_Poly[10].poly_num;
141: break;
142: case 24:
143: poly = crc_Poly[11].poly_num;
144: break;
145: case 30:
146: poly = crc_Poly[12].poly_num;
147: break;
148: case 32:
149: poly = crc_Poly[13].poly_num;
150: break;
151: default:
152: crc_Errno = 2;
153: strlcpy(crc_Error, "crcCalc(): Unsupported CRC method!!!", MAX_STR + 1);
154: return -1;
155: }
156: poly <<= bits;
157:
158: crchibit = (u_long) 1 << (crcBits - 1);
159: crchibit <<= bits;
160: crc = initCRC << bits;
161:
162: for (i = 0; i < bufLen; i++) {
163: ch = (u_long) *psBuf++;
164: if (RevOpts & REVOPTS_REVERTBYTE)
165: ch = crcReflect(ch, 8);
166:
167: for (j = 0x80; j; j >>= 1) {
168: b = crc & crchibit;
169: crc <<= 1;
170:
171: if (ch & j)
172: b ^= crchibit;
173: if (b)
174: crc ^= poly;
175: }
176: }
177:
178: if (RevOpts & REVOPTS_REVERTCRC)
179: crc = crcReflect(crc, sizeof(long) * 8);
180: crc ^= xorCRC << bits;
181: crc &= (((crchibit - 1) << 1) | 1);
182: if (!(RevOpts & REVOPTS_REVERTCRC))
183: crc >>= bits;
184:
185: crc_Errno ^= crc_Errno;
186: return crc;
187: }
188:
189: // ----------------------------------------------------------
190:
191: /*
192: * crcIP() Checksum in IP communication
193: * @nBuf = Data for calculation
194: * @bufLen = Length of data
195: * return: -1 error, !=-1 Checksum
196: */
197: inline u_short crcIP(u_short * __restrict nBuf, int bufLen)
198: {
199: register u_long sum;
200:
201: if (!nBuf) {
202: crc_Errno = 1;
203: strlcpy(crc_Error, "crcIP(): Invalid parameters!", MAX_STR + 1);
204: return -1;
205: }
206:
207: for (sum = 0; bufLen; bufLen--)
208: sum += *nBuf++;
209:
210: sum = (sum >> 16) + (sum & 0xFFFF);
211: sum += sum >> 16;
212:
213: crc_Errno ^= crc_Errno;
214: return (u_short) ~sum;
215: }
216:
217: /*
218: * crcFletcher() Fletcher-16 Checksum computing
219: * @nBuf = Data for calculation
220: * @bufLen = Length of data
221: * return: -1 error, !=-1 Checksum
222: */
223: inline u_long crcFletcher(u_short * __restrict nBuf, int bufLen)
224: {
225: register u_long s1, s2, clen;
226:
227: if (!nBuf) {
228: crc_Errno = 1;
229: strlcpy(crc_Error, "crcFletcher(): Invalid parameters!", MAX_STR + 1);
230: return -1;
231: }
232:
233: s1 = s2 = 0xFFFF;
234: while (bufLen) {
235: clen = bufLen > MAX_FLETCHER_DIGEST ? MAX_FLETCHER_DIGEST : bufLen;
236: bufLen -= clen;
237:
238: do {
239: s1 += (u_long) *nBuf++;
240: s2 += s1;
241: } while (--clen);
242:
243: s1 = (s1 >> 16) + (s1 & 0xFFFF);
244: s2 = (s2 >> 16) + (s2 & 0xFFFF);
245: }
246:
247: crc_Errno ^= crc_Errno;
248: return (s2 << 16) | s1;
249: }
250:
251: /*
252: * crcAdler() crcAdler-32 Checksum computing
253: * @psBuf = Data for calculation
254: * @bufLen = Length of data
255: * return: -1 error, !=-1 Checksum
256: */
257: inline u_long crcAdler(u_char * __restrict psBuf, int bufLen)
258: {
259: register u_long s1, s2, clen;
260:
261: if (!psBuf) {
262: crc_Errno = 1;
263: strlcpy(crc_Error, "crcAdler(): Invalid parameters!", MAX_STR + 1);
264: return -1;
265: }
266:
267: s1 = 1L;
268: s2 ^= s2;
269: while (bufLen) {
270: clen = bufLen > MAX_ADLER_DIGEST ? MAX_ADLER_DIGEST : bufLen;
271: bufLen -= clen;
272:
273: do {
274: s1 += (u_long) *psBuf++;
275: s2 += s1;
276: } while (--clen);
277:
278: s1 %= crc_modAdler;
279: s2 %= crc_modAdler;
280: }
281:
282: crc_Errno ^= crc_Errno;
283: return (s2 << 16) | s1;
284: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>