Annotation of libelwix/src/crc.c, revision 1.5.28.1
1.1 misho 1: /*************************************************************************
2: * (C) 2008 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
3: * by Michael Pounov <misho@openbsd-bg.org>
4: *
5: * $Author: misho $
1.5.28.1! misho 6: * $Id: crc.c,v 1.5 2017/12/08 00:07:48 misho Exp $
1.1 misho 7: *
8: **************************************************************************
9: The ELWIX and AITNET software is distributed under the following
10: terms:
11:
12: All of the documentation and software included in the ELWIX and AITNET
13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
14:
1.5.28.1! misho 15: Copyright 2004 - 2019
1.1 misho 16: by Michael Pounov <misho@elwix.org>. All rights reserved.
17:
18: Redistribution and use in source and binary forms, with or without
19: modification, are permitted provided that the following conditions
20: are met:
21: 1. Redistributions of source code must retain the above copyright
22: notice, this list of conditions and the following disclaimer.
23: 2. Redistributions in binary form must reproduce the above copyright
24: notice, this list of conditions and the following disclaimer in the
25: documentation and/or other materials provided with the distribution.
26: 3. All advertising materials mentioning features or use of this software
27: must display the following acknowledgement:
28: This product includes software developed by Michael Pounov <misho@elwix.org>
29: ELWIX - Embedded LightWeight unIX and its contributors.
30: 4. Neither the name of AITNET nor the names of its contributors
31: may be used to endorse or promote products derived from this software
32: without specific prior written permission.
33:
34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
37: ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
44: SUCH DAMAGE.
45: */
46: #include "global.h"
47:
48:
1.5.28.1! misho 49: /* CRC16 poly */
! 50: const u_short crc_16poly = 0x1021;
! 51:
1.1 misho 52: /* Adler module */
53: const u_int crc_modAdler = 0xFFF1L;
54:
55: /* All known library CRC types ... */
56: const crcPoly_t crc_Poly[] = {
57: { 1, (u_int) 0x1, "CRC-1-Parity" },
58: { 4, (u_int) 0x3, "CRC-4-ITU" },
59: { 5, (u_int) 0x15, "CRC-5-ITU" },
60: { 6, (u_int) 0x3, "CRC-6-ITU" },
61: { 7, (u_int) 0x9, "CRC-7-MMC" },
62: { 8, (u_int) 0x8D, "CRC-8-CCITT" },
63: { 10, (u_int) 0x233, "CRC-10" },
64: { 11, (u_int) 0x385, "CRC-11-FlexRay" },
65: { 12, (u_int) 0x80F, "CRC-12-Telco" },
66: { 15, (u_int) 0x4599, "CRC-15-CAN" },
67: { 16, (u_int) 0x8005, "CRC-16-IBM" },
68: { 24, (u_int) 0x864CFB, "CRC-24-Radix64" },
69: { 30, (u_int) 0x2030B9C7, "CRC-30-CDMA" },
70: { 32, (u_int) 0x04C11DB7, "CRC-32-802.3" }
71: };
72:
73:
74: /*
75: * crcReflect() - Reflect all bits of number
76: *
77: * @crcNum = Number for reflection
78: * @crcBits = Number width bits
1.5.28.1! misho 79: * return: reflecting number
1.1 misho 80: */
1.5 misho 81: u_int
1.1 misho 82: crcReflect(u_int crcNum, u_char crcBits)
83: {
1.2 misho 84: register u_int i, j = 1, rev = 0;
1.1 misho 85:
1.2 misho 86: for (i = (u_int) 1 << (crcBits - 1); i; i >>= 1, j <<= 1)
1.1 misho 87: if (crcNum & i)
88: rev |= j;
89: return rev;
90: }
91:
92: /*
93: * crcCalc() - Generic CRC calculation function for many sub variants of CRC algorithms
94: *
95: * @psBuf = Data for calculation
96: * @bufLen = Length of data
97: * @crcBits = CRC algorithm bits (1, 4, 5, 6, 7, 8, 10, 11, 12, 15, 16, 24, 30, 32)
98: * @RevOpts = Options for computation (REVOPTS_REVERTBYTE, REVOPTS_REVERTCRC)
99: * @initCRC = Initial CRC value
100: * @xorCRC = Last xor CRC value
1.5.28.1! misho 101: * return: CRC checksum
1.1 misho 102: */
1.5 misho 103: u_int
1.1 misho 104: crcCalc(u_char * __restrict psBuf, u_int bufLen, u_char crcBits, u_char RevOpts, u_int initCRC, u_int xorCRC)
105: {
106: const u_int bits = sizeof(int) * 8 - crcBits;
107: u_int poly, crchibit, crc;
108: register u_int i, j, b, ch;
109:
110: assert(psBuf);
111:
112: switch (crcBits) {
113: case 1:
114: poly = crc_Poly[0].poly_num;
115: break;
116: case 4:
117: poly = crc_Poly[1].poly_num;
118: break;
119: case 5:
120: poly = crc_Poly[2].poly_num;
121: break;
122: case 6:
123: poly = crc_Poly[3].poly_num;
124: break;
125: case 7:
126: poly = crc_Poly[4].poly_num;
127: break;
128: case 8:
129: poly = crc_Poly[5].poly_num;
130: break;
131: case 10:
132: poly = crc_Poly[6].poly_num;
133: break;
134: case 11:
135: poly = crc_Poly[7].poly_num;
136: break;
137: case 12:
138: poly = crc_Poly[8].poly_num;
139: break;
140: case 15:
141: poly = crc_Poly[9].poly_num;
142: break;
143: case 16:
144: poly = crc_Poly[10].poly_num;
145: break;
146: case 24:
147: poly = crc_Poly[11].poly_num;
148: break;
149: case 30:
150: poly = crc_Poly[12].poly_num;
151: break;
152: case 32:
153: poly = crc_Poly[13].poly_num;
154: break;
155: default:
156: elwix_SetErr(EINVAL, "crcCalc(): Unsupported CRC method!!!");
157: return -1;
158: }
159: poly <<= bits;
160:
161: crchibit = (u_int) 1 << (crcBits - 1);
162: crchibit <<= bits;
163: crc = initCRC << bits;
164:
165: for (i = 0; i < bufLen; i++) {
166: ch = (u_int) *psBuf++;
167: if (RevOpts & REVOPTS_REVERTBYTE)
168: ch = crcReflect(ch, 8);
169:
170: for (j = 0x80; j; j >>= 1) {
171: b = crc & crchibit;
172: crc <<= 1;
173:
174: if (ch & j)
175: b ^= crchibit;
176: if (b)
177: crc ^= poly;
178: }
179: }
180:
181: if (RevOpts & REVOPTS_REVERTCRC)
182: crc = crcReflect(crc, sizeof(int) * 8);
183: crc ^= xorCRC << bits;
184: crc &= (((crchibit - 1) << 1) | 1);
185: if (!(RevOpts & REVOPTS_REVERTCRC))
186: crc >>= bits;
187:
188: return crc;
189: }
190:
191:
192: /*
1.5.28.1! misho 193: * crc16() - Checksum in X/Y modem communication
! 194: *
! 195: * @buf = Data for calculation
! 196: * @bufLen = Length of data
! 197: * return: Checksum
! 198: */
! 199: u_short
! 200: crc16(u_char * __restrict buf, int bufLen)
! 201: {
! 202: u_short crc, x;
! 203: register u_short i;
! 204:
! 205: assert(buf);
! 206:
! 207: for (crc = 0; bufLen > 0; bufLen--, buf++)
! 208: for (i = 0x80; i; i >>= 1) {
! 209: x = crc >> 15;
! 210: crc <<= 1;
! 211:
! 212: if (*buf & i)
! 213: crc++;
! 214: if (x)
! 215: crc ^= crc_16poly;
! 216: }
! 217:
! 218: for (i = 0; i < 16; i++) {
! 219: x = crc >> 15;
! 220: crc <<= 1;
! 221:
! 222: if (x)
! 223: crc ^= crc_16poly;
! 224: }
! 225:
! 226: return crc;
! 227: }
! 228:
! 229: /*
1.1 misho 230: * crcIP() - Checksum in IP communication
231: *
232: * @buf = Data for calculation
233: * @bufLen = Length of data
1.5.28.1! misho 234: * return: Checksum
1.1 misho 235: */
1.5 misho 236: u_short
1.1 misho 237: crcIP(u_char * __restrict buf, int bufLen)
238: {
239: register u_int sum;
240: u_short last = 0, *nBuf = (u_short*) buf;
241:
242: assert(buf);
243:
1.5 misho 244: for (sum = 0; bufLen > 1; bufLen -= 2)
1.1 misho 245: sum += *nBuf++;
246: if (bufLen == 1) {
247: *(u_char*)(&last) += *(u_char*) nBuf;
248: sum += last;
249: }
250:
251: sum = (sum >> 16) + (sum & 0xFFFF);
252: sum += sum >> 16;
253:
254: return (u_short) ~sum;
255: }
256:
257: /*
1.5 misho 258: * crcTCP() - Checksum for TCP v4 communication
259: *
260: * @buf = Data for calculation
261: * @bufLen = Length of data
262: * @th = TCP header
1.5.28.1! misho 263: * return: Checksum
1.5 misho 264: */
265: u_short
266: crcTCP(struct in_addr src, struct in_addr dst, u_char * __restrict th)
267: {
268: struct psd_tcp {
269: struct in_addr src;
270: struct in_addr dst;
271: u_char pad;
272: u_char proto;
273: u_short tcp_len;
274: u_char tcp[20];
275: } buf;
276:
277: buf.src = src;
278: buf.dst = dst;
279: buf.pad = 0;
280: buf.proto = IPPROTO_TCP;
281: buf.tcp_len = htons(sizeof buf.tcp);
282: memcpy(&buf.tcp, th, sizeof buf.tcp);
283:
284: return crcIP((u_char*) &buf, sizeof buf);
285: }
286:
287: /*
288: * crcUDP() - Checksum for UDP v4 communication
289: *
290: * @buf = Data for calculation
291: * @bufLen = Length of data
292: * @uh = UDP header
1.5.28.1! misho 293: * return: Checksum
1.5 misho 294: */
295: u_short
296: crcUDP(struct in_addr src, struct in_addr dst, u_char * __restrict uh)
297: {
298: struct psd_udp {
299: struct in_addr src;
300: struct in_addr dst;
301: u_char pad;
302: u_char proto;
303: u_short udp_len;
304: u_char udp[8];
305: } buf;
306:
307: buf.src = src;
308: buf.dst = dst;
309: buf.pad = 0;
310: buf.proto = IPPROTO_UDP;
311: buf.udp_len = htons(sizeof buf.udp);
312: memcpy(&buf.udp, uh, sizeof buf.udp);
313:
314: return crcIP((u_char*) &buf, sizeof buf);
315: }
316:
317:
318: /*
1.1 misho 319: * crcFletcher16() - Fletcher-16 Checksum computing
320: *
321: * @nBuf = Data for calculation
322: * @bufLen = Length of data
1.5.28.1! misho 323: * return: Checksum
1.1 misho 324: */
1.5 misho 325: u_short
1.1 misho 326: crcFletcher16(u_short * __restrict nBuf, int bufLen)
327: {
328: register u_short s1, s2;
329: register u_int clen;
330:
331: assert(nBuf);
332:
333: s1 = s2 = 0xFF;
334: while (bufLen) {
335: clen = bufLen > MAX_FLETCHER16_DIGEST ? MAX_FLETCHER16_DIGEST : bufLen;
336: bufLen -= clen;
337:
338: do {
339: s1 += (u_short) *nBuf++;
340: s2 += s1;
341: } while (--clen);
342:
343: s1 = (s1 >> 8) + (s1 & 0xFF);
344: s2 = (s2 >> 8) + (s2 & 0xFF);
345: }
346:
347: return (s2 << 8) | s1;
348: }
349:
350: /*
351: * crcFletcher() - Fletcher-32 Checksum computing
352: *
353: * @nBuf = Data for calculation
354: * @bufLen = Length of data
1.5.28.1! misho 355: * return: Checksum
1.1 misho 356: */
1.5 misho 357: u_int
1.1 misho 358: crcFletcher(u_short * __restrict nBuf, int bufLen)
359: {
360: register u_int s1, s2, clen;
361:
362: assert(nBuf);
363:
364: s1 = s2 = 0xFFFF;
365: while (bufLen) {
366: clen = bufLen > MAX_FLETCHER_DIGEST ? MAX_FLETCHER_DIGEST : bufLen;
367: bufLen -= clen;
368:
369: do {
370: s1 += (u_int) *nBuf++;
371: s2 += s1;
372: } while (--clen);
373:
374: s1 = (s1 >> 16) + (s1 & 0xFFFF);
375: s2 = (s2 >> 16) + (s2 & 0xFFFF);
376: }
377:
378: return (s2 << 16) | s1;
379: }
380:
381: /*
382: * crcAdler() - crcAdler-32 Checksum computing
383: *
384: * @psBuf = Data for calculation
385: * @bufLen = Length of data
1.5.28.1! misho 386: * return: Checksum
1.1 misho 387: */
1.5 misho 388: u_int
1.1 misho 389: crcAdler(u_char * __restrict psBuf, int bufLen)
390: {
1.2 misho 391: register u_int s1 = 1, s2 = 0, clen;
1.1 misho 392:
393: assert(psBuf);
394:
395: while (bufLen) {
396: clen = bufLen > MAX_ADLER_DIGEST ? MAX_ADLER_DIGEST : bufLen;
397: bufLen -= clen;
398:
399: do {
400: s1 += (u_int) *psBuf++;
401: s2 += s1;
402: } while (--clen);
403:
404: s1 %= crc_modAdler;
405: s2 %= crc_modAdler;
406: }
407:
408: return (s2 << 16) | s1;
409: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>